Fix compilation error triggered with -Werror=sign-compare
[chromium-blink-merge.git] / ui / compositor / layer_unittest.cc
blobaf85fcf2ca6f2733ec8b6ad7997753b1149b51ab
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.
5 #include "base/basictypes.h"
6 #include "base/bind.h"
7 #include "base/compiler_specific.h"
8 #include "base/debug/trace_event.h"
9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/json/json_reader.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/path_service.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "cc/layers/delegated_frame_provider.h"
18 #include "cc/layers/delegated_frame_resource_collection.h"
19 #include "cc/layers/layer.h"
20 #include "cc/output/copy_output_request.h"
21 #include "cc/output/copy_output_result.h"
22 #include "cc/output/delegated_frame_data.h"
23 #include "cc/test/pixel_test_utils.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "ui/compositor/compositor_observer.h"
26 #include "ui/compositor/layer.h"
27 #include "ui/compositor/layer_animation_sequence.h"
28 #include "ui/compositor/layer_animator.h"
29 #include "ui/compositor/test/context_factories_for_test.h"
30 #include "ui/compositor/test/draw_waiter_for_test.h"
31 #include "ui/compositor/test/test_compositor_host.h"
32 #include "ui/compositor/test/test_layers.h"
33 #include "ui/gfx/canvas.h"
34 #include "ui/gfx/codec/png_codec.h"
35 #include "ui/gfx/gfx_paths.h"
36 #include "ui/gfx/skia_util.h"
38 using cc::MatchesPNGFile;
40 namespace ui {
42 namespace {
44 // There are three test classes in here that configure the Compositor and
45 // Layer's slightly differently:
46 // - LayerWithNullDelegateTest uses NullLayerDelegate as the LayerDelegate. This
47 // is typically the base class you want to use.
48 // - LayerWithDelegateTest uses LayerDelegate on the delegates.
49 // - LayerWithRealCompositorTest when a real compositor is required for testing.
50 // - Slow because they bring up a window and run the real compositor. This
51 // is typically not what you want.
53 class ColoredLayer : public Layer, public LayerDelegate {
54 public:
55 explicit ColoredLayer(SkColor color)
56 : Layer(LAYER_TEXTURED),
57 color_(color) {
58 set_delegate(this);
61 virtual ~ColoredLayer() { }
63 // Overridden from LayerDelegate:
64 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
65 canvas->DrawColor(color_);
68 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
71 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
72 return base::Closure();
75 private:
76 SkColor color_;
79 class LayerWithRealCompositorTest : public testing::Test {
80 public:
81 LayerWithRealCompositorTest() {
82 if (PathService::Get(gfx::DIR_TEST_DATA, &test_data_directory_)) {
83 test_data_directory_ = test_data_directory_.AppendASCII("compositor");
84 } else {
85 LOG(ERROR) << "Could not open test data directory.";
88 virtual ~LayerWithRealCompositorTest() {}
90 // Overridden from testing::Test:
91 virtual void SetUp() OVERRIDE {
92 bool enable_pixel_output = true;
93 ui::ContextFactory* context_factory =
94 InitializeContextFactoryForTests(enable_pixel_output);
96 const gfx::Rect host_bounds(10, 10, 500, 500);
97 compositor_host_.reset(TestCompositorHost::Create(
98 host_bounds, context_factory));
99 compositor_host_->Show();
102 virtual void TearDown() OVERRIDE {
103 compositor_host_.reset();
104 TerminateContextFactoryForTests();
107 Compositor* GetCompositor() { return compositor_host_->GetCompositor(); }
109 Layer* CreateLayer(LayerType type) {
110 return new Layer(type);
113 Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) {
114 Layer* layer = new ColoredLayer(color);
115 layer->SetBounds(bounds);
116 return layer;
119 Layer* CreateNoTextureLayer(const gfx::Rect& bounds) {
120 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
121 layer->SetBounds(bounds);
122 return layer;
125 void DrawTree(Layer* root) {
126 GetCompositor()->SetRootLayer(root);
127 GetCompositor()->ScheduleDraw();
128 WaitForDraw();
131 bool ReadPixels(SkBitmap* bitmap) {
132 return ReadPixels(bitmap, gfx::Rect(GetCompositor()->size()));
135 bool ReadPixels(SkBitmap* bitmap, gfx::Rect source_rect) {
136 scoped_refptr<ReadbackHolder> holder(new ReadbackHolder);
137 scoped_ptr<cc::CopyOutputRequest> request =
138 cc::CopyOutputRequest::CreateBitmapRequest(
139 base::Bind(&ReadbackHolder::OutputRequestCallback, holder));
140 request->set_area(source_rect);
142 GetCompositor()->root_layer()->RequestCopyOfOutput(request.Pass());
144 // Wait for copy response. This needs to wait as the compositor could
145 // be in the middle of a draw right now, and the commit with the
146 // copy output request may not be done on the first draw.
147 for (int i = 0; i < 2; i++) {
148 GetCompositor()->ScheduleDraw();
149 WaitForDraw();
152 if (holder->completed()) {
153 *bitmap = holder->result();
154 return true;
157 // Callback never called.
158 NOTREACHED();
159 return false;
162 void WaitForDraw() {
163 ui::DrawWaiterForTest::Wait(GetCompositor());
166 void WaitForCommit() {
167 ui::DrawWaiterForTest::WaitForCommit(GetCompositor());
170 // Invalidates the entire contents of the layer.
171 void SchedulePaintForLayer(Layer* layer) {
172 layer->SchedulePaint(
173 gfx::Rect(0, 0, layer->bounds().width(), layer->bounds().height()));
176 const base::FilePath& test_data_directory() const {
177 return test_data_directory_;
180 private:
181 class ReadbackHolder : public base::RefCountedThreadSafe<ReadbackHolder> {
182 public:
183 ReadbackHolder() : completed_(false) {}
185 void OutputRequestCallback(scoped_ptr<cc::CopyOutputResult> result) {
186 DCHECK(!completed_);
187 result_ = result->TakeBitmap();
188 completed_ = true;
190 bool completed() const {
191 return completed_;
193 const SkBitmap& result() const { return *result_; }
195 private:
196 friend class base::RefCountedThreadSafe<ReadbackHolder>;
198 virtual ~ReadbackHolder() {}
200 scoped_ptr<SkBitmap> result_;
201 bool completed_;
204 scoped_ptr<TestCompositorHost> compositor_host_;
206 // The root directory for test files.
207 base::FilePath test_data_directory_;
209 DISALLOW_COPY_AND_ASSIGN(LayerWithRealCompositorTest);
212 // LayerDelegate that paints colors to the layer.
213 class TestLayerDelegate : public LayerDelegate {
214 public:
215 explicit TestLayerDelegate() { reset(); }
216 virtual ~TestLayerDelegate() {}
218 void AddColor(SkColor color) {
219 colors_.push_back(color);
222 const gfx::Size& paint_size() const { return paint_size_; }
223 int color_index() const { return color_index_; }
225 std::string ToScaleString() const {
226 return base::StringPrintf("%.1f %.1f", scale_x_, scale_y_);
229 float device_scale_factor() const {
230 return device_scale_factor_;
233 // Overridden from LayerDelegate:
234 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
235 SkISize size = canvas->sk_canvas()->getBaseLayerSize();
236 paint_size_ = gfx::Size(size.width(), size.height());
237 canvas->FillRect(gfx::Rect(paint_size_), colors_[color_index_]);
238 color_index_ = (color_index_ + 1) % static_cast<int>(colors_.size());
239 const SkMatrix& matrix = canvas->sk_canvas()->getTotalMatrix();
240 scale_x_ = matrix.getScaleX();
241 scale_y_ = matrix.getScaleY();
244 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
245 device_scale_factor_ = device_scale_factor;
248 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
249 return base::Closure();
252 void reset() {
253 color_index_ = 0;
254 paint_size_.SetSize(0, 0);
255 scale_x_ = scale_y_ = 0.0f;
256 device_scale_factor_ = 0.0f;
259 private:
260 std::vector<SkColor> colors_;
261 int color_index_;
262 gfx::Size paint_size_;
263 float scale_x_;
264 float scale_y_;
265 float device_scale_factor_;
267 DISALLOW_COPY_AND_ASSIGN(TestLayerDelegate);
270 // LayerDelegate that verifies that a layer was asked to update its canvas.
271 class DrawTreeLayerDelegate : public LayerDelegate {
272 public:
273 DrawTreeLayerDelegate() : painted_(false) {}
274 virtual ~DrawTreeLayerDelegate() {}
276 void Reset() {
277 painted_ = false;
280 bool painted() const { return painted_; }
282 private:
283 // Overridden from LayerDelegate:
284 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
285 painted_ = true;
287 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
289 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
290 return base::Closure();
293 bool painted_;
295 DISALLOW_COPY_AND_ASSIGN(DrawTreeLayerDelegate);
298 // The simplest possible layer delegate. Does nothing.
299 class NullLayerDelegate : public LayerDelegate {
300 public:
301 NullLayerDelegate() {}
302 virtual ~NullLayerDelegate() {}
304 private:
305 // Overridden from LayerDelegate:
306 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
308 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
310 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
311 return base::Closure();
314 DISALLOW_COPY_AND_ASSIGN(NullLayerDelegate);
317 // Remembers if it has been notified.
318 class TestCompositorObserver : public CompositorObserver {
319 public:
320 TestCompositorObserver()
321 : committed_(false), started_(false), ended_(false), aborted_(false) {}
323 bool committed() const { return committed_; }
324 bool notified() const { return started_ && ended_; }
325 bool aborted() const { return aborted_; }
327 void Reset() {
328 committed_ = false;
329 started_ = false;
330 ended_ = false;
331 aborted_ = false;
334 private:
335 virtual void OnCompositingDidCommit(Compositor* compositor) OVERRIDE {
336 committed_ = true;
339 virtual void OnCompositingStarted(Compositor* compositor,
340 base::TimeTicks start_time) OVERRIDE {
341 started_ = true;
344 virtual void OnCompositingEnded(Compositor* compositor) OVERRIDE {
345 ended_ = true;
348 virtual void OnCompositingAborted(Compositor* compositor) OVERRIDE {
349 aborted_ = true;
352 virtual void OnCompositingLockStateChanged(Compositor* compositor) OVERRIDE {
355 bool committed_;
356 bool started_;
357 bool ended_;
358 bool aborted_;
360 DISALLOW_COPY_AND_ASSIGN(TestCompositorObserver);
363 } // namespace
365 TEST_F(LayerWithRealCompositorTest, Draw) {
366 scoped_ptr<Layer> layer(CreateColorLayer(SK_ColorRED,
367 gfx::Rect(20, 20, 50, 50)));
368 DrawTree(layer.get());
371 // Create this hierarchy:
372 // L1 - red
373 // +-- L2 - blue
374 // | +-- L3 - yellow
375 // +-- L4 - magenta
377 TEST_F(LayerWithRealCompositorTest, Hierarchy) {
378 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
379 gfx::Rect(20, 20, 400, 400)));
380 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
381 gfx::Rect(10, 10, 350, 350)));
382 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
383 gfx::Rect(5, 5, 25, 25)));
384 scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA,
385 gfx::Rect(300, 300, 100, 100)));
387 l1->Add(l2.get());
388 l1->Add(l4.get());
389 l2->Add(l3.get());
391 DrawTree(l1.get());
394 class LayerWithDelegateTest : public testing::Test {
395 public:
396 LayerWithDelegateTest() {}
397 virtual ~LayerWithDelegateTest() {}
399 // Overridden from testing::Test:
400 virtual void SetUp() OVERRIDE {
401 bool enable_pixel_output = false;
402 ui::ContextFactory* context_factory =
403 InitializeContextFactoryForTests(enable_pixel_output);
405 const gfx::Rect host_bounds(1000, 1000);
406 compositor_host_.reset(TestCompositorHost::Create(host_bounds,
407 context_factory));
408 compositor_host_->Show();
411 virtual void TearDown() OVERRIDE {
412 compositor_host_.reset();
413 TerminateContextFactoryForTests();
416 Compositor* compositor() { return compositor_host_->GetCompositor(); }
418 virtual Layer* CreateLayer(LayerType type) {
419 return new Layer(type);
422 Layer* CreateColorLayer(SkColor color, const gfx::Rect& bounds) {
423 Layer* layer = new ColoredLayer(color);
424 layer->SetBounds(bounds);
425 return layer;
428 virtual Layer* CreateNoTextureLayer(const gfx::Rect& bounds) {
429 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
430 layer->SetBounds(bounds);
431 return layer;
434 void DrawTree(Layer* root) {
435 compositor()->SetRootLayer(root);
436 Draw();
439 // Invalidates the entire contents of the layer.
440 void SchedulePaintForLayer(Layer* layer) {
441 layer->SchedulePaint(
442 gfx::Rect(0, 0, layer->bounds().width(), layer->bounds().height()));
445 // Invokes DrawTree on the compositor.
446 void Draw() {
447 compositor()->ScheduleDraw();
448 WaitForDraw();
451 void WaitForDraw() {
452 DrawWaiterForTest::Wait(compositor());
455 void WaitForCommit() {
456 DrawWaiterForTest::WaitForCommit(compositor());
459 private:
460 scoped_ptr<TestCompositorHost> compositor_host_;
462 DISALLOW_COPY_AND_ASSIGN(LayerWithDelegateTest);
465 // L1
466 // +-- L2
467 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Simple) {
468 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
469 gfx::Rect(20, 20, 400, 400)));
470 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
471 gfx::Rect(10, 10, 350, 350)));
472 l1->Add(l2.get());
473 DrawTree(l1.get());
475 gfx::Point point1_in_l2_coords(5, 5);
476 Layer::ConvertPointToLayer(l2.get(), l1.get(), &point1_in_l2_coords);
477 gfx::Point point1_in_l1_coords(15, 15);
478 EXPECT_EQ(point1_in_l1_coords, point1_in_l2_coords);
480 gfx::Point point2_in_l1_coords(5, 5);
481 Layer::ConvertPointToLayer(l1.get(), l2.get(), &point2_in_l1_coords);
482 gfx::Point point2_in_l2_coords(-5, -5);
483 EXPECT_EQ(point2_in_l2_coords, point2_in_l1_coords);
486 // L1
487 // +-- L2
488 // +-- L3
489 TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Medium) {
490 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
491 gfx::Rect(20, 20, 400, 400)));
492 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
493 gfx::Rect(10, 10, 350, 350)));
494 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
495 gfx::Rect(10, 10, 100, 100)));
496 l1->Add(l2.get());
497 l2->Add(l3.get());
498 DrawTree(l1.get());
500 gfx::Point point1_in_l3_coords(5, 5);
501 Layer::ConvertPointToLayer(l3.get(), l1.get(), &point1_in_l3_coords);
502 gfx::Point point1_in_l1_coords(25, 25);
503 EXPECT_EQ(point1_in_l1_coords, point1_in_l3_coords);
505 gfx::Point point2_in_l1_coords(5, 5);
506 Layer::ConvertPointToLayer(l1.get(), l3.get(), &point2_in_l1_coords);
507 gfx::Point point2_in_l3_coords(-15, -15);
508 EXPECT_EQ(point2_in_l3_coords, point2_in_l1_coords);
511 TEST_F(LayerWithRealCompositorTest, Delegate) {
512 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorBLACK,
513 gfx::Rect(20, 20, 400, 400)));
514 GetCompositor()->SetRootLayer(l1.get());
515 WaitForDraw();
517 TestLayerDelegate delegate;
518 l1->set_delegate(&delegate);
519 delegate.AddColor(SK_ColorWHITE);
520 delegate.AddColor(SK_ColorYELLOW);
521 delegate.AddColor(SK_ColorGREEN);
523 l1->SchedulePaint(gfx::Rect(0, 0, 400, 400));
524 WaitForDraw();
526 EXPECT_EQ(delegate.color_index(), 1);
527 EXPECT_EQ(delegate.paint_size(), l1->bounds().size());
529 l1->SchedulePaint(gfx::Rect(10, 10, 200, 200));
530 WaitForDraw();
531 EXPECT_EQ(delegate.color_index(), 2);
532 EXPECT_EQ(delegate.paint_size(), gfx::Size(200, 200));
534 l1->SchedulePaint(gfx::Rect(5, 5, 50, 50));
535 WaitForDraw();
536 EXPECT_EQ(delegate.color_index(), 0);
537 EXPECT_EQ(delegate.paint_size(), gfx::Size(50, 50));
540 TEST_F(LayerWithRealCompositorTest, DrawTree) {
541 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
542 gfx::Rect(20, 20, 400, 400)));
543 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
544 gfx::Rect(10, 10, 350, 350)));
545 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
546 gfx::Rect(10, 10, 100, 100)));
547 l1->Add(l2.get());
548 l2->Add(l3.get());
550 GetCompositor()->SetRootLayer(l1.get());
551 WaitForDraw();
553 DrawTreeLayerDelegate d1;
554 l1->set_delegate(&d1);
555 DrawTreeLayerDelegate d2;
556 l2->set_delegate(&d2);
557 DrawTreeLayerDelegate d3;
558 l3->set_delegate(&d3);
560 l2->SchedulePaint(gfx::Rect(5, 5, 5, 5));
561 WaitForDraw();
562 EXPECT_FALSE(d1.painted());
563 EXPECT_TRUE(d2.painted());
564 EXPECT_FALSE(d3.painted());
567 // Tests no-texture Layers.
568 // Create this hierarchy:
569 // L1 - red
570 // +-- L2 - NO TEXTURE
571 // | +-- L3 - yellow
572 // +-- L4 - magenta
574 TEST_F(LayerWithRealCompositorTest, HierarchyNoTexture) {
575 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
576 gfx::Rect(20, 20, 400, 400)));
577 scoped_ptr<Layer> l2(CreateNoTextureLayer(gfx::Rect(10, 10, 350, 350)));
578 scoped_ptr<Layer> l3(CreateColorLayer(SK_ColorYELLOW,
579 gfx::Rect(5, 5, 25, 25)));
580 scoped_ptr<Layer> l4(CreateColorLayer(SK_ColorMAGENTA,
581 gfx::Rect(300, 300, 100, 100)));
583 l1->Add(l2.get());
584 l1->Add(l4.get());
585 l2->Add(l3.get());
587 GetCompositor()->SetRootLayer(l1.get());
588 WaitForDraw();
590 DrawTreeLayerDelegate d2;
591 l2->set_delegate(&d2);
592 DrawTreeLayerDelegate d3;
593 l3->set_delegate(&d3);
595 l2->SchedulePaint(gfx::Rect(5, 5, 5, 5));
596 l3->SchedulePaint(gfx::Rect(5, 5, 5, 5));
597 WaitForDraw();
599 // |d2| should not have received a paint notification since it has no texture.
600 EXPECT_FALSE(d2.painted());
601 // |d3| should have received a paint notification.
602 EXPECT_TRUE(d3.painted());
605 class LayerWithNullDelegateTest : public LayerWithDelegateTest {
606 public:
607 LayerWithNullDelegateTest() {}
608 virtual ~LayerWithNullDelegateTest() {}
610 virtual void SetUp() OVERRIDE {
611 LayerWithDelegateTest::SetUp();
612 default_layer_delegate_.reset(new NullLayerDelegate());
615 virtual Layer* CreateLayer(LayerType type) OVERRIDE {
616 Layer* layer = new Layer(type);
617 layer->set_delegate(default_layer_delegate_.get());
618 return layer;
621 Layer* CreateTextureRootLayer(const gfx::Rect& bounds) {
622 Layer* layer = CreateTextureLayer(bounds);
623 compositor()->SetRootLayer(layer);
624 return layer;
627 Layer* CreateTextureLayer(const gfx::Rect& bounds) {
628 Layer* layer = CreateLayer(LAYER_TEXTURED);
629 layer->SetBounds(bounds);
630 return layer;
633 virtual Layer* CreateNoTextureLayer(const gfx::Rect& bounds) OVERRIDE {
634 Layer* layer = CreateLayer(LAYER_NOT_DRAWN);
635 layer->SetBounds(bounds);
636 return layer;
639 private:
640 scoped_ptr<NullLayerDelegate> default_layer_delegate_;
642 DISALLOW_COPY_AND_ASSIGN(LayerWithNullDelegateTest);
645 TEST_F(LayerWithNullDelegateTest, EscapedDebugNames) {
646 scoped_ptr<Layer> layer(CreateLayer(LAYER_NOT_DRAWN));
647 std::string name = "\"\'\\/\b\f\n\r\t\n";
648 layer->set_name(name);
649 scoped_refptr<base::debug::ConvertableToTraceFormat> debug_info =
650 layer->TakeDebugInfo();
651 EXPECT_TRUE(!!debug_info);
652 std::string json;
653 debug_info->AppendAsTraceFormat(&json);
654 base::JSONReader json_reader;
655 scoped_ptr<base::Value> debug_info_value(json_reader.ReadToValue(json));
656 EXPECT_TRUE(!!debug_info_value);
657 EXPECT_TRUE(debug_info_value->IsType(base::Value::TYPE_DICTIONARY));
658 base::DictionaryValue* dictionary = 0;
659 EXPECT_TRUE(debug_info_value->GetAsDictionary(&dictionary));
660 std::string roundtrip;
661 EXPECT_TRUE(dictionary->GetString("layer_name", &roundtrip));
662 EXPECT_EQ(name, roundtrip);
665 void ReturnMailbox(bool* run, uint32 sync_point, bool is_lost) {
666 *run = true;
669 TEST_F(LayerWithNullDelegateTest, SwitchLayerPreservesCCLayerState) {
670 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
671 gfx::Rect(20, 20, 400, 400)));
672 l1->SetFillsBoundsOpaquely(true);
673 l1->SetForceRenderSurface(true);
674 l1->SetVisible(false);
676 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
677 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
678 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
679 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
680 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
682 cc::Layer* before_layer = l1->cc_layer();
684 bool callback1_run = false;
685 cc::TextureMailbox mailbox(gpu::Mailbox::Generate(), 0, 0);
686 l1->SetTextureMailbox(mailbox,
687 cc::SingleReleaseCallback::Create(
688 base::Bind(ReturnMailbox, &callback1_run)),
689 gfx::Size(1, 1));
691 EXPECT_NE(before_layer, l1->cc_layer());
693 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
694 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
695 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
696 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
697 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
698 EXPECT_FALSE(callback1_run);
700 bool callback2_run = false;
701 mailbox = cc::TextureMailbox(gpu::Mailbox::Generate(), 0, 0);
702 l1->SetTextureMailbox(mailbox,
703 cc::SingleReleaseCallback::Create(
704 base::Bind(ReturnMailbox, &callback2_run)),
705 gfx::Size(1, 1));
706 EXPECT_TRUE(callback1_run);
707 EXPECT_FALSE(callback2_run);
709 l1->SetShowPaintedContent();
710 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
711 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
712 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
713 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
714 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
715 EXPECT_TRUE(callback2_run);
718 // Various visibile/drawn assertions.
719 TEST_F(LayerWithNullDelegateTest, Visibility) {
720 scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
721 scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
722 scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
723 l1->Add(l2.get());
724 l2->Add(l3.get());
726 NullLayerDelegate delegate;
727 l1->set_delegate(&delegate);
728 l2->set_delegate(&delegate);
729 l3->set_delegate(&delegate);
731 // Layers should initially be drawn.
732 EXPECT_TRUE(l1->IsDrawn());
733 EXPECT_TRUE(l2->IsDrawn());
734 EXPECT_TRUE(l3->IsDrawn());
735 EXPECT_FALSE(l1->cc_layer()->hide_layer_and_subtree());
736 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
737 EXPECT_FALSE(l3->cc_layer()->hide_layer_and_subtree());
739 compositor()->SetRootLayer(l1.get());
741 Draw();
743 l1->SetVisible(false);
744 EXPECT_FALSE(l1->IsDrawn());
745 EXPECT_FALSE(l2->IsDrawn());
746 EXPECT_FALSE(l3->IsDrawn());
747 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
748 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
749 EXPECT_FALSE(l3->cc_layer()->hide_layer_and_subtree());
751 l3->SetVisible(false);
752 EXPECT_FALSE(l1->IsDrawn());
753 EXPECT_FALSE(l2->IsDrawn());
754 EXPECT_FALSE(l3->IsDrawn());
755 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
756 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
757 EXPECT_TRUE(l3->cc_layer()->hide_layer_and_subtree());
759 l1->SetVisible(true);
760 EXPECT_TRUE(l1->IsDrawn());
761 EXPECT_TRUE(l2->IsDrawn());
762 EXPECT_FALSE(l3->IsDrawn());
763 EXPECT_FALSE(l1->cc_layer()->hide_layer_and_subtree());
764 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
765 EXPECT_TRUE(l3->cc_layer()->hide_layer_and_subtree());
768 // Checks that stacking-related methods behave as advertised.
769 TEST_F(LayerWithNullDelegateTest, Stacking) {
770 scoped_ptr<Layer> root(new Layer(LAYER_NOT_DRAWN));
771 scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
772 scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
773 scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
774 l1->set_name("1");
775 l2->set_name("2");
776 l3->set_name("3");
777 root->Add(l3.get());
778 root->Add(l2.get());
779 root->Add(l1.get());
781 // Layers' children are stored in bottom-to-top order.
782 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
784 root->StackAtTop(l3.get());
785 EXPECT_EQ("2 1 3", test::ChildLayerNamesAsString(*root.get()));
787 root->StackAtTop(l1.get());
788 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
790 root->StackAtTop(l1.get());
791 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
793 root->StackAbove(l2.get(), l3.get());
794 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
796 root->StackAbove(l1.get(), l3.get());
797 EXPECT_EQ("3 1 2", test::ChildLayerNamesAsString(*root.get()));
799 root->StackAbove(l2.get(), l1.get());
800 EXPECT_EQ("3 1 2", test::ChildLayerNamesAsString(*root.get()));
802 root->StackAtBottom(l2.get());
803 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
805 root->StackAtBottom(l3.get());
806 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
808 root->StackAtBottom(l3.get());
809 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
811 root->StackBelow(l2.get(), l3.get());
812 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
814 root->StackBelow(l1.get(), l3.get());
815 EXPECT_EQ("2 1 3", test::ChildLayerNamesAsString(*root.get()));
817 root->StackBelow(l3.get(), l2.get());
818 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
820 root->StackBelow(l3.get(), l2.get());
821 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
823 root->StackBelow(l3.get(), l1.get());
824 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
827 // Verifies SetBounds triggers the appropriate painting/drawing.
828 TEST_F(LayerWithNullDelegateTest, SetBoundsSchedulesPaint) {
829 scoped_ptr<Layer> l1(CreateTextureLayer(gfx::Rect(0, 0, 200, 200)));
830 compositor()->SetRootLayer(l1.get());
832 Draw();
834 l1->SetBounds(gfx::Rect(5, 5, 200, 200));
836 // The CompositorDelegate (us) should have been told to draw for a move.
837 WaitForDraw();
839 l1->SetBounds(gfx::Rect(5, 5, 100, 100));
841 // The CompositorDelegate (us) should have been told to draw for a resize.
842 WaitForDraw();
845 // Checks that pixels are actually drawn to the screen with a read back.
846 TEST_F(LayerWithRealCompositorTest, DrawPixels) {
847 gfx::Size viewport_size = GetCompositor()->size();
849 // The window should be some non-trivial size but may not be exactly
850 // 500x500 on all platforms/bots.
851 EXPECT_GE(viewport_size.width(), 200);
852 EXPECT_GE(viewport_size.height(), 200);
854 int blue_height = 10;
856 scoped_ptr<Layer> layer(
857 CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
858 scoped_ptr<Layer> layer2(
859 CreateColorLayer(SK_ColorBLUE,
860 gfx::Rect(0, 0, viewport_size.width(), blue_height)));
862 layer->Add(layer2.get());
864 DrawTree(layer.get());
866 SkBitmap bitmap;
867 ASSERT_TRUE(ReadPixels(&bitmap, gfx::Rect(viewport_size)));
868 ASSERT_FALSE(bitmap.empty());
870 SkAutoLockPixels lock(bitmap);
871 for (int x = 0; x < viewport_size.width(); x++) {
872 for (int y = 0; y < viewport_size.height(); y++) {
873 SkColor actual_color = bitmap.getColor(x, y);
874 SkColor expected_color = y < blue_height ? SK_ColorBLUE : SK_ColorRED;
875 EXPECT_EQ(expected_color, actual_color)
876 << "Pixel error at x=" << x << " y=" << y << "; "
877 << "actual RGBA=("
878 << SkColorGetR(actual_color) << ","
879 << SkColorGetG(actual_color) << ","
880 << SkColorGetB(actual_color) << ","
881 << SkColorGetA(actual_color) << "); "
882 << "expected RGBA=("
883 << SkColorGetR(expected_color) << ","
884 << SkColorGetG(expected_color) << ","
885 << SkColorGetB(expected_color) << ","
886 << SkColorGetA(expected_color) << ")";
891 // Checks the logic around Compositor::SetRootLayer and Layer::SetCompositor.
892 TEST_F(LayerWithRealCompositorTest, SetRootLayer) {
893 Compositor* compositor = GetCompositor();
894 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
895 gfx::Rect(20, 20, 400, 400)));
896 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
897 gfx::Rect(10, 10, 350, 350)));
899 EXPECT_EQ(NULL, l1->GetCompositor());
900 EXPECT_EQ(NULL, l2->GetCompositor());
902 compositor->SetRootLayer(l1.get());
903 EXPECT_EQ(compositor, l1->GetCompositor());
905 l1->Add(l2.get());
906 EXPECT_EQ(compositor, l2->GetCompositor());
908 l1->Remove(l2.get());
909 EXPECT_EQ(NULL, l2->GetCompositor());
911 l1->Add(l2.get());
912 EXPECT_EQ(compositor, l2->GetCompositor());
914 compositor->SetRootLayer(NULL);
915 EXPECT_EQ(NULL, l1->GetCompositor());
916 EXPECT_EQ(NULL, l2->GetCompositor());
919 // Checks that compositor observers are notified when:
920 // - DrawTree is called,
921 // - After ScheduleDraw is called, or
922 // - Whenever SetBounds, SetOpacity or SetTransform are called.
923 // TODO(vollick): could be reorganized into compositor_unittest.cc
924 TEST_F(LayerWithRealCompositorTest, CompositorObservers) {
925 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
926 gfx::Rect(20, 20, 400, 400)));
927 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
928 gfx::Rect(10, 10, 350, 350)));
929 l1->Add(l2.get());
930 TestCompositorObserver observer;
931 GetCompositor()->AddObserver(&observer);
933 // Explicitly called DrawTree should cause the observers to be notified.
934 // NOTE: this call to DrawTree sets l1 to be the compositor's root layer.
935 DrawTree(l1.get());
936 EXPECT_TRUE(observer.notified());
938 // ScheduleDraw without any visible change should cause a commit.
939 observer.Reset();
940 l1->ScheduleDraw();
941 WaitForCommit();
942 EXPECT_TRUE(observer.committed());
944 // Moving, but not resizing, a layer should alert the observers.
945 observer.Reset();
946 l2->SetBounds(gfx::Rect(0, 0, 350, 350));
947 WaitForDraw();
948 EXPECT_TRUE(observer.notified());
950 // So should resizing a layer.
951 observer.Reset();
952 l2->SetBounds(gfx::Rect(0, 0, 400, 400));
953 WaitForDraw();
954 EXPECT_TRUE(observer.notified());
956 // Opacity changes should alert the observers.
957 observer.Reset();
958 l2->SetOpacity(0.5f);
959 WaitForDraw();
960 EXPECT_TRUE(observer.notified());
962 // So should setting the opacity back.
963 observer.Reset();
964 l2->SetOpacity(1.0f);
965 WaitForDraw();
966 EXPECT_TRUE(observer.notified());
968 // Setting the transform of a layer should alert the observers.
969 observer.Reset();
970 gfx::Transform transform;
971 transform.Translate(200.0, 200.0);
972 transform.Rotate(90.0);
973 transform.Translate(-200.0, -200.0);
974 l2->SetTransform(transform);
975 WaitForDraw();
976 EXPECT_TRUE(observer.notified());
978 // A change resulting in an aborted swap buffer should alert the observer
979 // and also signal an abort.
980 observer.Reset();
981 l2->SetOpacity(0.1f);
982 GetCompositor()->DidAbortSwapBuffers();
983 WaitForDraw();
984 EXPECT_TRUE(observer.notified());
985 EXPECT_TRUE(observer.aborted());
987 GetCompositor()->RemoveObserver(&observer);
989 // Opacity changes should no longer alert the removed observer.
990 observer.Reset();
991 l2->SetOpacity(0.5f);
992 WaitForDraw();
994 EXPECT_FALSE(observer.notified());
997 // Checks that modifying the hierarchy correctly affects final composite.
998 TEST_F(LayerWithRealCompositorTest, ModifyHierarchy) {
999 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(50, 50));
1001 // l0
1002 // +-l11
1003 // | +-l21
1004 // +-l12
1005 scoped_ptr<Layer> l0(CreateColorLayer(SK_ColorRED,
1006 gfx::Rect(0, 0, 50, 50)));
1007 scoped_ptr<Layer> l11(CreateColorLayer(SK_ColorGREEN,
1008 gfx::Rect(0, 0, 25, 25)));
1009 scoped_ptr<Layer> l21(CreateColorLayer(SK_ColorMAGENTA,
1010 gfx::Rect(0, 0, 15, 15)));
1011 scoped_ptr<Layer> l12(CreateColorLayer(SK_ColorBLUE,
1012 gfx::Rect(10, 10, 25, 25)));
1014 base::FilePath ref_img1 =
1015 test_data_directory().AppendASCII("ModifyHierarchy1.png");
1016 base::FilePath ref_img2 =
1017 test_data_directory().AppendASCII("ModifyHierarchy2.png");
1018 SkBitmap bitmap;
1020 l0->Add(l11.get());
1021 l11->Add(l21.get());
1022 l0->Add(l12.get());
1023 DrawTree(l0.get());
1024 ASSERT_TRUE(ReadPixels(&bitmap));
1025 ASSERT_FALSE(bitmap.empty());
1026 // WritePNGFile(bitmap, ref_img1);
1027 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1029 l0->StackAtTop(l11.get());
1030 DrawTree(l0.get());
1031 ASSERT_TRUE(ReadPixels(&bitmap));
1032 ASSERT_FALSE(bitmap.empty());
1033 // WritePNGFile(bitmap, ref_img2);
1034 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1036 // should restore to original configuration
1037 l0->StackAbove(l12.get(), l11.get());
1038 DrawTree(l0.get());
1039 ASSERT_TRUE(ReadPixels(&bitmap));
1040 ASSERT_FALSE(bitmap.empty());
1041 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1043 // l11 back to front
1044 l0->StackAtTop(l11.get());
1045 DrawTree(l0.get());
1046 ASSERT_TRUE(ReadPixels(&bitmap));
1047 ASSERT_FALSE(bitmap.empty());
1048 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1050 // should restore to original configuration
1051 l0->StackAbove(l12.get(), l11.get());
1052 DrawTree(l0.get());
1053 ASSERT_TRUE(ReadPixels(&bitmap));
1054 ASSERT_FALSE(bitmap.empty());
1055 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1057 // l11 back to front
1058 l0->StackAbove(l11.get(), l12.get());
1059 DrawTree(l0.get());
1060 ASSERT_TRUE(ReadPixels(&bitmap));
1061 ASSERT_FALSE(bitmap.empty());
1062 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1065 // Opacity is rendered correctly.
1066 // Checks that modifying the hierarchy correctly affects final composite.
1067 TEST_F(LayerWithRealCompositorTest, Opacity) {
1068 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(50, 50));
1070 // l0
1071 // +-l11
1072 scoped_ptr<Layer> l0(CreateColorLayer(SK_ColorRED,
1073 gfx::Rect(0, 0, 50, 50)));
1074 scoped_ptr<Layer> l11(CreateColorLayer(SK_ColorGREEN,
1075 gfx::Rect(0, 0, 25, 25)));
1077 base::FilePath ref_img = test_data_directory().AppendASCII("Opacity.png");
1079 l11->SetOpacity(0.75);
1080 l0->Add(l11.get());
1081 DrawTree(l0.get());
1082 SkBitmap bitmap;
1083 ASSERT_TRUE(ReadPixels(&bitmap));
1084 ASSERT_FALSE(bitmap.empty());
1085 // WritePNGFile(bitmap, ref_img);
1086 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img, cc::ExactPixelComparator(true)));
1089 namespace {
1091 class SchedulePaintLayerDelegate : public LayerDelegate {
1092 public:
1093 SchedulePaintLayerDelegate() : paint_count_(0), layer_(NULL) {}
1095 virtual ~SchedulePaintLayerDelegate() {}
1097 void set_layer(Layer* layer) {
1098 layer_ = layer;
1099 layer_->set_delegate(this);
1102 void SetSchedulePaintRect(const gfx::Rect& rect) {
1103 schedule_paint_rect_ = rect;
1106 int GetPaintCountAndClear() {
1107 int value = paint_count_;
1108 paint_count_ = 0;
1109 return value;
1112 const gfx::RectF& last_clip_rect() const { return last_clip_rect_; }
1114 private:
1115 // Overridden from LayerDelegate:
1116 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
1117 paint_count_++;
1118 if (!schedule_paint_rect_.IsEmpty()) {
1119 layer_->SchedulePaint(schedule_paint_rect_);
1120 schedule_paint_rect_ = gfx::Rect();
1122 SkRect sk_clip_rect;
1123 if (canvas->sk_canvas()->getClipBounds(&sk_clip_rect))
1124 last_clip_rect_ = gfx::SkRectToRectF(sk_clip_rect);
1127 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
1130 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
1131 return base::Closure();
1134 int paint_count_;
1135 Layer* layer_;
1136 gfx::Rect schedule_paint_rect_;
1137 gfx::RectF last_clip_rect_;
1139 DISALLOW_COPY_AND_ASSIGN(SchedulePaintLayerDelegate);
1142 } // namespace
1144 // Verifies that if SchedulePaint is invoked during painting the layer is still
1145 // marked dirty.
1146 TEST_F(LayerWithDelegateTest, SchedulePaintFromOnPaintLayer) {
1147 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorRED,
1148 gfx::Rect(0, 0, 500, 500)));
1149 SchedulePaintLayerDelegate child_delegate;
1150 scoped_ptr<Layer> child(CreateColorLayer(SK_ColorBLUE,
1151 gfx::Rect(0, 0, 200, 200)));
1152 child_delegate.set_layer(child.get());
1154 root->Add(child.get());
1156 SchedulePaintForLayer(root.get());
1157 DrawTree(root.get());
1158 child->SchedulePaint(gfx::Rect(0, 0, 20, 20));
1159 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1161 // Set a rect so that when OnPaintLayer() is invoked SchedulePaint is invoked
1162 // again.
1163 child_delegate.SetSchedulePaintRect(gfx::Rect(10, 10, 30, 30));
1164 WaitForCommit();
1165 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1167 // Because SchedulePaint() was invoked from OnPaintLayer() |child| should
1168 // still need to be painted.
1169 WaitForCommit();
1170 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1171 EXPECT_TRUE(child_delegate.last_clip_rect().Contains(
1172 gfx::Rect(10, 10, 30, 30)));
1175 TEST_F(LayerWithRealCompositorTest, ScaleUpDown) {
1176 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorWHITE,
1177 gfx::Rect(10, 20, 200, 220)));
1178 TestLayerDelegate root_delegate;
1179 root_delegate.AddColor(SK_ColorWHITE);
1180 root->set_delegate(&root_delegate);
1182 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorWHITE,
1183 gfx::Rect(10, 20, 140, 180)));
1184 TestLayerDelegate l1_delegate;
1185 l1_delegate.AddColor(SK_ColorWHITE);
1186 l1->set_delegate(&l1_delegate);
1188 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1189 GetCompositor()->SetRootLayer(root.get());
1190 root->Add(l1.get());
1191 WaitForDraw();
1193 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1194 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1195 gfx::Size cc_bounds_size = root->cc_layer()->bounds();
1196 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1197 cc_bounds_size = l1->cc_layer()->bounds();
1198 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1199 // No scale change, so no scale notification.
1200 EXPECT_EQ(0.0f, root_delegate.device_scale_factor());
1201 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1203 EXPECT_EQ("200x220", root_delegate.paint_size().ToString());
1204 EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1206 // Scale up to 2.0. Changing scale doesn't change the bounds in DIP.
1207 GetCompositor()->SetScaleAndSize(2.0f, gfx::Size(500, 500));
1208 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1209 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1210 // CC layer should still match the UI layer bounds.
1211 cc_bounds_size = root->cc_layer()->bounds();
1212 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1213 cc_bounds_size = l1->cc_layer()->bounds();
1214 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1215 // New scale factor must have been notified.
1216 EXPECT_EQ(2.0f, root_delegate.device_scale_factor());
1217 EXPECT_EQ(2.0f, l1_delegate.device_scale_factor());
1219 // Canvas size must have been scaled down up.
1220 WaitForDraw();
1221 EXPECT_EQ("400x440", root_delegate.paint_size().ToString());
1222 EXPECT_EQ("2.0 2.0", root_delegate.ToScaleString());
1223 EXPECT_EQ("280x360", l1_delegate.paint_size().ToString());
1224 EXPECT_EQ("2.0 2.0", l1_delegate.ToScaleString());
1226 // Scale down back to 1.0f.
1227 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1228 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1229 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1230 // CC layer should still match the UI layer bounds.
1231 cc_bounds_size = root->cc_layer()->bounds();
1232 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1233 cc_bounds_size = l1->cc_layer()->bounds();
1234 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1235 // New scale factor must have been notified.
1236 EXPECT_EQ(1.0f, root_delegate.device_scale_factor());
1237 EXPECT_EQ(1.0f, l1_delegate.device_scale_factor());
1239 // Canvas size must have been scaled down too.
1240 WaitForDraw();
1241 EXPECT_EQ("200x220", root_delegate.paint_size().ToString());
1242 EXPECT_EQ("1.0 1.0", root_delegate.ToScaleString());
1243 EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1244 EXPECT_EQ("1.0 1.0", l1_delegate.ToScaleString());
1246 root_delegate.reset();
1247 l1_delegate.reset();
1248 // Just changing the size shouldn't notify the scale change nor
1249 // trigger repaint.
1250 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(1000, 1000));
1251 // No scale change, so no scale notification.
1252 EXPECT_EQ(0.0f, root_delegate.device_scale_factor());
1253 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1254 WaitForDraw();
1255 EXPECT_EQ("0x0", root_delegate.paint_size().ToString());
1256 EXPECT_EQ("0.0 0.0", root_delegate.ToScaleString());
1257 EXPECT_EQ("0x0", l1_delegate.paint_size().ToString());
1258 EXPECT_EQ("0.0 0.0", l1_delegate.ToScaleString());
1261 TEST_F(LayerWithRealCompositorTest, ScaleReparent) {
1262 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorWHITE,
1263 gfx::Rect(10, 20, 200, 220)));
1264 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorWHITE,
1265 gfx::Rect(10, 20, 140, 180)));
1266 TestLayerDelegate l1_delegate;
1267 l1_delegate.AddColor(SK_ColorWHITE);
1268 l1->set_delegate(&l1_delegate);
1270 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1271 GetCompositor()->SetRootLayer(root.get());
1272 WaitForDraw();
1274 root->Add(l1.get());
1275 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1276 gfx::Size cc_bounds_size = l1->cc_layer()->bounds();
1277 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1278 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1280 WaitForDraw();
1281 EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1282 EXPECT_EQ("1.0 1.0", l1_delegate.ToScaleString());
1284 // Remove l1 from root and change the scale.
1285 root->Remove(l1.get());
1286 EXPECT_EQ(NULL, l1->parent());
1287 EXPECT_EQ(NULL, l1->GetCompositor());
1288 GetCompositor()->SetScaleAndSize(2.0f, gfx::Size(500, 500));
1289 // Sanity check on root and l1.
1290 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1291 cc_bounds_size = l1->cc_layer()->bounds();
1292 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1294 root->Add(l1.get());
1295 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1296 cc_bounds_size = l1->cc_layer()->bounds();
1297 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1298 EXPECT_EQ(2.0f, l1_delegate.device_scale_factor());
1299 WaitForDraw();
1300 EXPECT_EQ("280x360", l1_delegate.paint_size().ToString());
1301 EXPECT_EQ("2.0 2.0", l1_delegate.ToScaleString());
1304 // Verifies that when changing bounds on a layer that is invisible, and then
1305 // made visible, the right thing happens:
1306 // - if just a move, then no painting should happen.
1307 // - if a resize, the layer should be repainted.
1308 TEST_F(LayerWithDelegateTest, SetBoundsWhenInvisible) {
1309 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1311 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1312 child->SetBounds(gfx::Rect(0, 0, 500, 500));
1313 DrawTreeLayerDelegate delegate;
1314 child->set_delegate(&delegate);
1315 root->Add(child.get());
1317 // Paint once for initial damage.
1318 child->SetVisible(true);
1319 DrawTree(root.get());
1321 // Reset into invisible state.
1322 child->SetVisible(false);
1323 DrawTree(root.get());
1324 delegate.Reset();
1326 // Move layer.
1327 child->SetBounds(gfx::Rect(200, 200, 500, 500));
1328 child->SetVisible(true);
1329 DrawTree(root.get());
1330 EXPECT_FALSE(delegate.painted());
1332 // Reset into invisible state.
1333 child->SetVisible(false);
1334 DrawTree(root.get());
1335 delegate.Reset();
1337 // Resize layer.
1338 child->SetBounds(gfx::Rect(200, 200, 400, 400));
1339 child->SetVisible(true);
1340 DrawTree(root.get());
1341 EXPECT_TRUE(delegate.painted());
1344 static scoped_ptr<cc::DelegatedFrameData> MakeFrameData(gfx::Size size) {
1345 scoped_ptr<cc::DelegatedFrameData> frame_data(new cc::DelegatedFrameData);
1346 scoped_ptr<cc::RenderPass> render_pass(cc::RenderPass::Create());
1347 render_pass->SetNew(
1348 cc::RenderPass::Id(1, 1), gfx::Rect(size), gfx::Rect(), gfx::Transform());
1349 frame_data->render_pass_list.push_back(render_pass.Pass());
1350 return frame_data.Pass();
1353 TEST_F(LayerWithDelegateTest, DelegatedLayer) {
1354 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1356 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1358 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1359 child->SetVisible(true);
1360 root->Add(child.get());
1361 DrawTree(root.get());
1363 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1364 new cc::DelegatedFrameResourceCollection;
1365 scoped_refptr<cc::DelegatedFrameProvider> frame_provider;
1367 // Content matches layer size.
1368 frame_provider = new cc::DelegatedFrameProvider(
1369 resource_collection.get(), MakeFrameData(gfx::Size(10, 10)));
1370 child->SetShowDelegatedContent(frame_provider, gfx::Size(10, 10));
1371 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1372 gfx::Size(10, 10).ToString());
1374 // Content larger than layer.
1375 child->SetBounds(gfx::Rect(0, 0, 5, 5));
1376 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1377 gfx::Size(5, 5).ToString());
1379 // Content smaller than layer.
1380 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1381 frame_provider = new cc::DelegatedFrameProvider(
1382 resource_collection.get(), MakeFrameData(gfx::Size(5, 5)));
1383 child->SetShowDelegatedContent(frame_provider, gfx::Size(5, 5));
1384 EXPECT_EQ(child->cc_layer()->bounds().ToString(), gfx::Size(5, 5).ToString());
1386 // Hi-DPI content on low-DPI layer.
1387 frame_provider = new cc::DelegatedFrameProvider(
1388 resource_collection.get(), MakeFrameData(gfx::Size(20, 20)));
1389 child->SetShowDelegatedContent(frame_provider, gfx::Size(10, 10));
1390 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1391 gfx::Size(10, 10).ToString());
1393 // Hi-DPI content on hi-DPI layer.
1394 compositor()->SetScaleAndSize(2.f, gfx::Size(1000, 1000));
1395 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1396 gfx::Size(10, 10).ToString());
1398 // Low-DPI content on hi-DPI layer.
1399 frame_provider = new cc::DelegatedFrameProvider(
1400 resource_collection.get(), MakeFrameData(gfx::Size(10, 10)));
1401 child->SetShowDelegatedContent(frame_provider, gfx::Size(10, 10));
1402 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1403 gfx::Size(10, 10).ToString());
1406 TEST_F(LayerWithDelegateTest, ExternalContent) {
1407 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1408 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1410 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1411 child->SetVisible(true);
1412 root->Add(child.get());
1414 // The layer is already showing painted content, so the cc layer won't change.
1415 scoped_refptr<cc::Layer> before = child->cc_layer();
1416 child->SetShowPaintedContent();
1417 EXPECT_TRUE(child->cc_layer());
1418 EXPECT_EQ(before, child->cc_layer());
1420 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1421 new cc::DelegatedFrameResourceCollection;
1422 scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
1423 new cc::DelegatedFrameProvider(resource_collection.get(),
1424 MakeFrameData(gfx::Size(10, 10)));
1426 // Showing delegated content changes the underlying cc layer.
1427 before = child->cc_layer();
1428 child->SetShowDelegatedContent(frame_provider, gfx::Size(10, 10));
1429 EXPECT_TRUE(child->cc_layer());
1430 EXPECT_NE(before, child->cc_layer());
1432 // Changing to painted content should change the underlying cc layer.
1433 before = child->cc_layer();
1434 child->SetShowPaintedContent();
1435 EXPECT_TRUE(child->cc_layer());
1436 EXPECT_NE(before, child->cc_layer());
1439 // Tests Layer::AddThreadedAnimation and Layer::RemoveThreadedAnimation.
1440 TEST_F(LayerWithRealCompositorTest, AddRemoveThreadedAnimations) {
1441 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1442 scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
1443 scoped_ptr<Layer> l2(CreateLayer(LAYER_TEXTURED));
1445 l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1446 l2->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1448 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1450 // Trigger a threaded animation.
1451 l1->SetOpacity(0.5f);
1453 EXPECT_TRUE(l1->HasPendingThreadedAnimations());
1455 // Ensure we can remove a pending threaded animation.
1456 l1->GetAnimator()->StopAnimating();
1458 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1460 // Trigger another threaded animation.
1461 l1->SetOpacity(0.2f);
1463 EXPECT_TRUE(l1->HasPendingThreadedAnimations());
1465 root->Add(l1.get());
1466 GetCompositor()->SetRootLayer(root.get());
1468 // Now that l1 is part of a tree, it should have dispatched the pending
1469 // animation.
1470 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1472 // Ensure that l1 no longer holds on to animations.
1473 l1->SetOpacity(0.1f);
1474 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1476 // Ensure that adding a layer to an existing tree causes its pending
1477 // animations to get dispatched.
1478 l2->SetOpacity(0.5f);
1479 EXPECT_TRUE(l2->HasPendingThreadedAnimations());
1481 l1->Add(l2.get());
1482 EXPECT_FALSE(l2->HasPendingThreadedAnimations());
1485 // Tests that in-progress threaded animations complete when a Layer's
1486 // cc::Layer changes.
1487 TEST_F(LayerWithRealCompositorTest, SwitchCCLayerAnimations) {
1488 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1489 scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
1490 GetCompositor()->SetRootLayer(root.get());
1491 root->Add(l1.get());
1493 l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1495 EXPECT_FLOAT_EQ(l1->opacity(), 1.0f);
1497 // Trigger a threaded animation.
1498 l1->SetOpacity(0.5f);
1500 // Change l1's cc::Layer.
1501 l1->SwitchCCLayerForTest();
1503 // Ensure that the opacity animation completed.
1504 EXPECT_FLOAT_EQ(l1->opacity(), 0.5f);
1507 // Tests that the animators in the layer tree is added to the
1508 // animator-collection when the root-layer is set to the compositor.
1509 TEST_F(LayerWithDelegateTest, RootLayerAnimatorsInCompositor) {
1510 scoped_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR));
1511 scoped_ptr<Layer> child(CreateColorLayer(SK_ColorRED, gfx::Rect(10, 10)));
1512 child->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1513 child->SetOpacity(0.5f);
1514 root->Add(child.get());
1516 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1517 compositor()->SetRootLayer(root.get());
1518 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1521 // Tests that adding/removing a layer adds/removes the animator from its entire
1522 // subtree from the compositor's animator-collection.
1523 TEST_F(LayerWithDelegateTest, AddRemoveLayerUpdatesAnimatorsFromSubtree) {
1524 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1525 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1526 scoped_ptr<Layer> grandchild(CreateColorLayer(SK_ColorRED,
1527 gfx::Rect(10, 10)));
1528 root->Add(child.get());
1529 child->Add(grandchild.get());
1530 compositor()->SetRootLayer(root.get());
1532 grandchild->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1533 grandchild->SetOpacity(0.5f);
1534 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1536 root->Remove(child.get());
1537 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1539 root->Add(child.get());
1540 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1543 TEST_F(LayerWithDelegateTest, DestroyingLayerRemovesTheAnimatorFromCollection) {
1544 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1545 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1546 root->Add(child.get());
1547 compositor()->SetRootLayer(root.get());
1549 child->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1550 child->SetOpacity(0.5f);
1551 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1553 child.reset();
1554 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1557 } // namespace ui