ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / ui / compositor / layer_unittest.cc
blobd64ac74eecf2833e63bd3fbf6505c0a9362390af
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/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/json/json_reader.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/path_service.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/trace_event/trace_event.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/dip_util.h"
27 #include "ui/compositor/layer.h"
28 #include "ui/compositor/layer_animation_sequence.h"
29 #include "ui/compositor/layer_animator.h"
30 #include "ui/compositor/test/context_factories_for_test.h"
31 #include "ui/compositor/test/draw_waiter_for_test.h"
32 #include "ui/compositor/test/test_compositor_host.h"
33 #include "ui/compositor/test/test_layers.h"
34 #include "ui/gfx/canvas.h"
35 #include "ui/gfx/codec/png_codec.h"
36 #include "ui/gfx/gfx_paths.h"
37 #include "ui/gfx/skia_util.h"
39 using cc::MatchesPNGFile;
41 namespace ui {
43 namespace {
45 // There are three test classes in here that configure the Compositor and
46 // Layer's slightly differently:
47 // - LayerWithNullDelegateTest uses NullLayerDelegate as the LayerDelegate. This
48 // is typically the base class you want to use.
49 // - LayerWithDelegateTest uses LayerDelegate on the delegates.
50 // - LayerWithRealCompositorTest when a real compositor is required for testing.
51 // - Slow because they bring up a window and run the real compositor. This
52 // is typically not what you want.
54 class ColoredLayer : public Layer, public LayerDelegate {
55 public:
56 explicit ColoredLayer(SkColor color)
57 : Layer(LAYER_TEXTURED),
58 color_(color) {
59 set_delegate(this);
62 ~ColoredLayer() override {}
64 // Overridden from LayerDelegate:
65 void OnPaintLayer(gfx::Canvas* canvas) override { canvas->DrawColor(color_); }
67 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
69 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
71 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 ~LayerWithRealCompositorTest() override {}
90 // Overridden from testing::Test:
91 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(
98 TestCompositorHost::Create(host_bounds, context_factory));
99 compositor_host_->Show();
102 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 WaitForSwap();
131 void ReadPixels(SkBitmap* bitmap) {
132 ReadPixels(bitmap, gfx::Rect(GetCompositor()->size()));
135 void 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()->ScheduleFullRedraw();
149 WaitForDraw();
152 // Waits for the callback to finish run and return result.
153 holder->WaitForReadback();
155 *bitmap = holder->result();
158 void WaitForDraw() {
159 ui::DrawWaiterForTest::WaitForCompositingStarted(GetCompositor());
162 void WaitForSwap() {
163 DrawWaiterForTest::WaitForCompositingEnded(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() : run_loop_(new base::RunLoop) {}
185 void OutputRequestCallback(scoped_ptr<cc::CopyOutputResult> result) {
186 result_ = result->TakeBitmap();
187 run_loop_->Quit();
190 void WaitForReadback() { run_loop_->Run(); }
192 const SkBitmap& result() const { return *result_; }
194 private:
195 friend class base::RefCountedThreadSafe<ReadbackHolder>;
197 virtual ~ReadbackHolder() {}
199 scoped_ptr<SkBitmap> result_;
200 scoped_ptr<base::RunLoop> run_loop_;
203 scoped_ptr<TestCompositorHost> compositor_host_;
205 // The root directory for test files.
206 base::FilePath test_data_directory_;
208 DISALLOW_COPY_AND_ASSIGN(LayerWithRealCompositorTest);
211 // LayerDelegate that paints colors to the layer.
212 class TestLayerDelegate : public LayerDelegate {
213 public:
214 explicit TestLayerDelegate() { reset(); }
215 ~TestLayerDelegate() override {}
217 void AddColor(SkColor color) {
218 colors_.push_back(color);
221 const gfx::Size& paint_size() const { return paint_size_; }
222 int color_index() const { return color_index_; }
224 std::string ToScaleString() const {
225 return base::StringPrintf("%.1f %.1f", scale_x_, scale_y_);
228 float device_scale_factor() const {
229 return device_scale_factor_;
232 // Overridden from LayerDelegate:
233 void OnPaintLayer(gfx::Canvas* canvas) override {
234 SkISize size = canvas->sk_canvas()->getBaseLayerSize();
235 paint_size_ = gfx::Size(size.width(), size.height());
236 canvas->DrawColor(colors_[color_index_]);
237 color_index_ = (color_index_ + 1) % static_cast<int>(colors_.size());
238 const SkMatrix& matrix = canvas->sk_canvas()->getTotalMatrix();
239 scale_x_ = matrix.getScaleX();
240 scale_y_ = matrix.getScaleY();
243 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
245 void OnDeviceScaleFactorChanged(float device_scale_factor) override {
246 device_scale_factor_ = device_scale_factor;
249 base::Closure PrepareForLayerBoundsChange() override {
250 return base::Closure();
253 void reset() {
254 color_index_ = 0;
255 paint_size_.SetSize(0, 0);
256 scale_x_ = scale_y_ = 0.0f;
257 device_scale_factor_ = 0.0f;
260 private:
261 std::vector<SkColor> colors_;
262 int color_index_;
263 gfx::Size paint_size_;
264 float scale_x_;
265 float scale_y_;
266 float device_scale_factor_;
268 DISALLOW_COPY_AND_ASSIGN(TestLayerDelegate);
271 // LayerDelegate that verifies that a layer was asked to update its canvas.
272 class DrawTreeLayerDelegate : public LayerDelegate {
273 public:
274 DrawTreeLayerDelegate() : painted_(false) {}
275 ~DrawTreeLayerDelegate() override {}
277 void Reset() {
278 painted_ = false;
281 bool painted() const { return painted_; }
283 private:
284 // Overridden from LayerDelegate:
285 void OnPaintLayer(gfx::Canvas* canvas) override {
286 painted_ = true;
287 canvas->DrawColor(SK_ColorWHITE);
289 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
290 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
291 base::Closure PrepareForLayerBoundsChange() override {
292 return base::Closure();
295 bool painted_;
297 DISALLOW_COPY_AND_ASSIGN(DrawTreeLayerDelegate);
300 // The simplest possible layer delegate. Does nothing.
301 class NullLayerDelegate : public LayerDelegate {
302 public:
303 NullLayerDelegate() {}
304 ~NullLayerDelegate() override {}
306 private:
307 // Overridden from LayerDelegate:
308 void OnPaintLayer(gfx::Canvas* canvas) override {}
309 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
310 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
311 base::Closure PrepareForLayerBoundsChange() override {
312 return base::Closure();
315 DISALLOW_COPY_AND_ASSIGN(NullLayerDelegate);
318 // Remembers if it has been notified.
319 class TestCompositorObserver : public CompositorObserver {
320 public:
321 TestCompositorObserver()
322 : committed_(false), started_(false), ended_(false), aborted_(false) {}
324 bool committed() const { return committed_; }
325 bool notified() const { return started_ && ended_; }
326 bool aborted() const { return aborted_; }
328 void Reset() {
329 committed_ = false;
330 started_ = false;
331 ended_ = false;
332 aborted_ = false;
335 private:
336 void OnCompositingDidCommit(Compositor* compositor) override {
337 committed_ = true;
340 void OnCompositingStarted(Compositor* compositor,
341 base::TimeTicks start_time) override {
342 started_ = true;
345 void OnCompositingEnded(Compositor* compositor) override { ended_ = true; }
347 void OnCompositingAborted(Compositor* compositor) override {
348 aborted_ = true;
351 void OnCompositingLockStateChanged(Compositor* compositor) override {}
353 void OnCompositingShuttingDown(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 ~LayerWithDelegateTest() override {}
399 // Overridden from testing::Test:
400 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 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::WaitForCompositingStarted(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 ~LayerWithNullDelegateTest() override {}
610 void SetUp() override {
611 LayerWithDelegateTest::SetUp();
612 default_layer_delegate_.reset(new NullLayerDelegate());
615 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 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::trace_event::ConvertableToTraceFormat> debug_info =
650 layer->TakeDebugInfo();
651 EXPECT_TRUE(!!debug_info.get());
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(CreateLayer(LAYER_SOLID_COLOR));
671 l1->SetFillsBoundsOpaquely(true);
672 l1->SetForceRenderSurface(true);
673 l1->SetVisible(false);
674 l1->SetBounds(gfx::Rect(4, 5));
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());
681 EXPECT_EQ(gfx::Size(4, 5), l1->cc_layer()->bounds());
683 cc::Layer* before_layer = l1->cc_layer();
685 bool callback1_run = false;
686 cc::TextureMailbox mailbox(gpu::Mailbox::Generate(), 0, 0);
687 l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(
688 base::Bind(ReturnMailbox, &callback1_run)),
689 gfx::Size(10, 10));
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_EQ(gfx::Size(4, 5), l1->cc_layer()->bounds());
699 EXPECT_FALSE(callback1_run);
701 bool callback2_run = false;
702 mailbox = cc::TextureMailbox(gpu::Mailbox::Generate(), 0, 0);
703 l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(
704 base::Bind(ReturnMailbox, &callback2_run)),
705 gfx::Size(10, 10));
706 EXPECT_TRUE(callback1_run);
707 EXPECT_FALSE(callback2_run);
709 // Show solid color instead.
710 l1->SetShowSolidColorContent();
711 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
712 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
713 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
714 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
715 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
716 EXPECT_EQ(gfx::Size(4, 5), l1->cc_layer()->bounds());
717 EXPECT_TRUE(callback2_run);
719 before_layer = l1->cc_layer();
721 // Back to a texture, without changing the bounds of the layer or the texture.
722 bool callback3_run = false;
723 mailbox = cc::TextureMailbox(gpu::Mailbox::Generate(), 0, 0);
724 l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(
725 base::Bind(ReturnMailbox, &callback3_run)),
726 gfx::Size(10, 10));
728 EXPECT_NE(before_layer, l1->cc_layer());
730 EXPECT_EQ(gfx::Point3F(), l1->cc_layer()->transform_origin());
731 EXPECT_TRUE(l1->cc_layer()->DrawsContent());
732 EXPECT_TRUE(l1->cc_layer()->contents_opaque());
733 EXPECT_TRUE(l1->cc_layer()->force_render_surface());
734 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
735 EXPECT_EQ(gfx::Size(4, 5), l1->cc_layer()->bounds());
736 EXPECT_FALSE(callback3_run);
738 // Release the on |l1| mailbox to clean up the test.
739 l1->SetShowSolidColorContent();
742 // Various visibile/drawn assertions.
743 TEST_F(LayerWithNullDelegateTest, Visibility) {
744 scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
745 scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
746 scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
747 l1->Add(l2.get());
748 l2->Add(l3.get());
750 NullLayerDelegate delegate;
751 l1->set_delegate(&delegate);
752 l2->set_delegate(&delegate);
753 l3->set_delegate(&delegate);
755 // Layers should initially be drawn.
756 EXPECT_TRUE(l1->IsDrawn());
757 EXPECT_TRUE(l2->IsDrawn());
758 EXPECT_TRUE(l3->IsDrawn());
759 EXPECT_FALSE(l1->cc_layer()->hide_layer_and_subtree());
760 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
761 EXPECT_FALSE(l3->cc_layer()->hide_layer_and_subtree());
763 compositor()->SetRootLayer(l1.get());
765 Draw();
767 l1->SetVisible(false);
768 EXPECT_FALSE(l1->IsDrawn());
769 EXPECT_FALSE(l2->IsDrawn());
770 EXPECT_FALSE(l3->IsDrawn());
771 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
772 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
773 EXPECT_FALSE(l3->cc_layer()->hide_layer_and_subtree());
775 l3->SetVisible(false);
776 EXPECT_FALSE(l1->IsDrawn());
777 EXPECT_FALSE(l2->IsDrawn());
778 EXPECT_FALSE(l3->IsDrawn());
779 EXPECT_TRUE(l1->cc_layer()->hide_layer_and_subtree());
780 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
781 EXPECT_TRUE(l3->cc_layer()->hide_layer_and_subtree());
783 l1->SetVisible(true);
784 EXPECT_TRUE(l1->IsDrawn());
785 EXPECT_TRUE(l2->IsDrawn());
786 EXPECT_FALSE(l3->IsDrawn());
787 EXPECT_FALSE(l1->cc_layer()->hide_layer_and_subtree());
788 EXPECT_FALSE(l2->cc_layer()->hide_layer_and_subtree());
789 EXPECT_TRUE(l3->cc_layer()->hide_layer_and_subtree());
792 // Checks that stacking-related methods behave as advertised.
793 TEST_F(LayerWithNullDelegateTest, Stacking) {
794 scoped_ptr<Layer> root(new Layer(LAYER_NOT_DRAWN));
795 scoped_ptr<Layer> l1(new Layer(LAYER_TEXTURED));
796 scoped_ptr<Layer> l2(new Layer(LAYER_TEXTURED));
797 scoped_ptr<Layer> l3(new Layer(LAYER_TEXTURED));
798 l1->set_name("1");
799 l2->set_name("2");
800 l3->set_name("3");
801 root->Add(l3.get());
802 root->Add(l2.get());
803 root->Add(l1.get());
805 // Layers' children are stored in bottom-to-top order.
806 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
808 root->StackAtTop(l3.get());
809 EXPECT_EQ("2 1 3", test::ChildLayerNamesAsString(*root.get()));
811 root->StackAtTop(l1.get());
812 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
814 root->StackAtTop(l1.get());
815 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
817 root->StackAbove(l2.get(), l3.get());
818 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
820 root->StackAbove(l1.get(), l3.get());
821 EXPECT_EQ("3 1 2", test::ChildLayerNamesAsString(*root.get()));
823 root->StackAbove(l2.get(), l1.get());
824 EXPECT_EQ("3 1 2", test::ChildLayerNamesAsString(*root.get()));
826 root->StackAtBottom(l2.get());
827 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
829 root->StackAtBottom(l3.get());
830 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
832 root->StackAtBottom(l3.get());
833 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
835 root->StackBelow(l2.get(), l3.get());
836 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
838 root->StackBelow(l1.get(), l3.get());
839 EXPECT_EQ("2 1 3", test::ChildLayerNamesAsString(*root.get()));
841 root->StackBelow(l3.get(), l2.get());
842 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
844 root->StackBelow(l3.get(), l2.get());
845 EXPECT_EQ("3 2 1", test::ChildLayerNamesAsString(*root.get()));
847 root->StackBelow(l3.get(), l1.get());
848 EXPECT_EQ("2 3 1", test::ChildLayerNamesAsString(*root.get()));
851 // Verifies SetBounds triggers the appropriate painting/drawing.
852 TEST_F(LayerWithNullDelegateTest, SetBoundsSchedulesPaint) {
853 scoped_ptr<Layer> l1(CreateTextureLayer(gfx::Rect(0, 0, 200, 200)));
854 compositor()->SetRootLayer(l1.get());
856 Draw();
858 l1->SetBounds(gfx::Rect(5, 5, 200, 200));
860 // The CompositorDelegate (us) should have been told to draw for a move.
861 WaitForDraw();
863 l1->SetBounds(gfx::Rect(5, 5, 100, 100));
865 // The CompositorDelegate (us) should have been told to draw for a resize.
866 WaitForDraw();
869 void ExpectRgba(int x, int y, SkColor expected_color, SkColor actual_color) {
870 EXPECT_EQ(expected_color, actual_color)
871 << "Pixel error at x=" << x << " y=" << y << "; "
872 << "actual RGBA=("
873 << SkColorGetR(actual_color) << ","
874 << SkColorGetG(actual_color) << ","
875 << SkColorGetB(actual_color) << ","
876 << SkColorGetA(actual_color) << "); "
877 << "expected RGBA=("
878 << SkColorGetR(expected_color) << ","
879 << SkColorGetG(expected_color) << ","
880 << SkColorGetB(expected_color) << ","
881 << SkColorGetA(expected_color) << ")";
884 // Checks that pixels are actually drawn to the screen with a read back.
885 TEST_F(LayerWithRealCompositorTest, DrawPixels) {
886 gfx::Size viewport_size = GetCompositor()->size();
888 // The window should be some non-trivial size but may not be exactly
889 // 500x500 on all platforms/bots.
890 EXPECT_GE(viewport_size.width(), 200);
891 EXPECT_GE(viewport_size.height(), 200);
893 int blue_height = 10;
895 scoped_ptr<Layer> layer(
896 CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
897 scoped_ptr<Layer> layer2(
898 CreateColorLayer(SK_ColorBLUE,
899 gfx::Rect(0, 0, viewport_size.width(), blue_height)));
901 layer->Add(layer2.get());
903 DrawTree(layer.get());
905 SkBitmap bitmap;
906 ReadPixels(&bitmap, gfx::Rect(viewport_size));
907 ASSERT_FALSE(bitmap.empty());
909 SkAutoLockPixels lock(bitmap);
910 for (int x = 0; x < viewport_size.width(); x++) {
911 for (int y = 0; y < viewport_size.height(); y++) {
912 SkColor actual_color = bitmap.getColor(x, y);
913 SkColor expected_color = y < blue_height ? SK_ColorBLUE : SK_ColorRED;
914 ExpectRgba(x, y, expected_color, actual_color);
919 // Checks that drawing a layer with transparent pixels is blended correctly
920 // with the lower layer.
921 TEST_F(LayerWithRealCompositorTest, DrawAlphaBlendedPixels) {
922 gfx::Size viewport_size = GetCompositor()->size();
924 int test_size = 200;
925 EXPECT_GE(viewport_size.width(), test_size);
926 EXPECT_GE(viewport_size.height(), test_size);
928 // Blue with a wee bit of transparency.
929 SkColor blue_with_alpha = SkColorSetARGBInline(40, 10, 20, 200);
930 SkColor blend_color = SkColorSetARGBInline(255, 216, 3, 32);
932 scoped_ptr<Layer> background_layer(
933 CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
934 scoped_ptr<Layer> foreground_layer(
935 CreateColorLayer(blue_with_alpha, gfx::Rect(viewport_size)));
937 // This must be set to false for layers with alpha to be blended correctly.
938 foreground_layer->SetFillsBoundsOpaquely(false);
940 background_layer->Add(foreground_layer.get());
941 DrawTree(background_layer.get());
943 SkBitmap bitmap;
944 ReadPixels(&bitmap, gfx::Rect(viewport_size));
945 ASSERT_FALSE(bitmap.empty());
947 SkAutoLockPixels lock(bitmap);
948 for (int x = 0; x < test_size; x++) {
949 for (int y = 0; y < test_size; y++) {
950 SkColor actual_color = bitmap.getColor(x, y);
951 ExpectRgba(x, y, blend_color, actual_color);
956 // Checks that using the AlphaShape filter applied to a layer with
957 // transparency, alpha-blends properly with the layer below.
958 TEST_F(LayerWithRealCompositorTest, DrawAlphaThresholdFilterPixels) {
959 gfx::Size viewport_size = GetCompositor()->size();
961 int test_size = 200;
962 EXPECT_GE(viewport_size.width(), test_size);
963 EXPECT_GE(viewport_size.height(), test_size);
965 int blue_height = 10;
966 SkColor blue_with_alpha = SkColorSetARGBInline(40, 0, 0, 255);
967 SkColor blend_color = SkColorSetARGBInline(255, 215, 0, 40);
969 scoped_ptr<Layer> background_layer(
970 CreateColorLayer(SK_ColorRED, gfx::Rect(viewport_size)));
971 scoped_ptr<Layer> foreground_layer(
972 CreateColorLayer(blue_with_alpha, gfx::Rect(viewport_size)));
974 // Add a shape to restrict the visible part of the layer.
975 SkRegion shape;
976 shape.setRect(0, 0, viewport_size.width(), blue_height);
977 foreground_layer->SetAlphaShape(make_scoped_ptr(new SkRegion(shape)));
979 foreground_layer->SetFillsBoundsOpaquely(false);
981 background_layer->Add(foreground_layer.get());
982 DrawTree(background_layer.get());
984 SkBitmap bitmap;
985 ReadPixels(&bitmap, gfx::Rect(viewport_size));
986 ASSERT_FALSE(bitmap.empty());
988 SkAutoLockPixels lock(bitmap);
989 for (int x = 0; x < test_size; x++) {
990 for (int y = 0; y < test_size; y++) {
991 SkColor actual_color = bitmap.getColor(x, y);
992 ExpectRgba(x, y, actual_color,
993 y < blue_height ? blend_color : SK_ColorRED);
998 // Checks the logic around Compositor::SetRootLayer and Layer::SetCompositor.
999 TEST_F(LayerWithRealCompositorTest, SetRootLayer) {
1000 Compositor* compositor = GetCompositor();
1001 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
1002 gfx::Rect(20, 20, 400, 400)));
1003 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
1004 gfx::Rect(10, 10, 350, 350)));
1006 EXPECT_EQ(NULL, l1->GetCompositor());
1007 EXPECT_EQ(NULL, l2->GetCompositor());
1009 compositor->SetRootLayer(l1.get());
1010 EXPECT_EQ(compositor, l1->GetCompositor());
1012 l1->Add(l2.get());
1013 EXPECT_EQ(compositor, l2->GetCompositor());
1015 l1->Remove(l2.get());
1016 EXPECT_EQ(NULL, l2->GetCompositor());
1018 l1->Add(l2.get());
1019 EXPECT_EQ(compositor, l2->GetCompositor());
1021 compositor->SetRootLayer(NULL);
1022 EXPECT_EQ(NULL, l1->GetCompositor());
1023 EXPECT_EQ(NULL, l2->GetCompositor());
1026 // Checks that compositor observers are notified when:
1027 // - DrawTree is called,
1028 // - After ScheduleDraw is called, or
1029 // - Whenever SetBounds, SetOpacity or SetTransform are called.
1030 // TODO(vollick): could be reorganized into compositor_unittest.cc
1031 TEST_F(LayerWithRealCompositorTest, CompositorObservers) {
1032 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorRED,
1033 gfx::Rect(20, 20, 400, 400)));
1034 scoped_ptr<Layer> l2(CreateColorLayer(SK_ColorBLUE,
1035 gfx::Rect(10, 10, 350, 350)));
1036 l1->Add(l2.get());
1037 TestCompositorObserver observer;
1038 GetCompositor()->AddObserver(&observer);
1040 // Explicitly called DrawTree should cause the observers to be notified.
1041 // NOTE: this call to DrawTree sets l1 to be the compositor's root layer.
1042 DrawTree(l1.get());
1043 EXPECT_TRUE(observer.notified());
1045 // ScheduleDraw without any visible change should cause a commit.
1046 observer.Reset();
1047 l1->ScheduleDraw();
1048 WaitForCommit();
1049 EXPECT_TRUE(observer.committed());
1051 // Moving, but not resizing, a layer should alert the observers.
1052 observer.Reset();
1053 l2->SetBounds(gfx::Rect(0, 0, 350, 350));
1054 WaitForSwap();
1055 EXPECT_TRUE(observer.notified());
1057 // So should resizing a layer.
1058 observer.Reset();
1059 l2->SetBounds(gfx::Rect(0, 0, 400, 400));
1060 WaitForSwap();
1061 EXPECT_TRUE(observer.notified());
1063 // Opacity changes should alert the observers.
1064 observer.Reset();
1065 l2->SetOpacity(0.5f);
1066 WaitForSwap();
1067 EXPECT_TRUE(observer.notified());
1069 // So should setting the opacity back.
1070 observer.Reset();
1071 l2->SetOpacity(1.0f);
1072 WaitForSwap();
1073 EXPECT_TRUE(observer.notified());
1075 // Setting the transform of a layer should alert the observers.
1076 observer.Reset();
1077 gfx::Transform transform;
1078 transform.Translate(200.0, 200.0);
1079 transform.Rotate(90.0);
1080 transform.Translate(-200.0, -200.0);
1081 l2->SetTransform(transform);
1082 WaitForSwap();
1083 EXPECT_TRUE(observer.notified());
1085 // A change resulting in an aborted swap buffer should alert the observer
1086 // and also signal an abort.
1087 observer.Reset();
1088 l2->SetOpacity(0.1f);
1089 GetCompositor()->DidAbortSwapBuffers();
1090 WaitForSwap();
1091 EXPECT_TRUE(observer.notified());
1092 EXPECT_TRUE(observer.aborted());
1094 GetCompositor()->RemoveObserver(&observer);
1096 // Opacity changes should no longer alert the removed observer.
1097 observer.Reset();
1098 l2->SetOpacity(0.5f);
1099 WaitForSwap();
1101 EXPECT_FALSE(observer.notified());
1104 // Checks that modifying the hierarchy correctly affects final composite.
1105 TEST_F(LayerWithRealCompositorTest, ModifyHierarchy) {
1106 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(50, 50));
1108 // l0
1109 // +-l11
1110 // | +-l21
1111 // +-l12
1112 scoped_ptr<Layer> l0(CreateColorLayer(SK_ColorRED,
1113 gfx::Rect(0, 0, 50, 50)));
1114 scoped_ptr<Layer> l11(CreateColorLayer(SK_ColorGREEN,
1115 gfx::Rect(0, 0, 25, 25)));
1116 scoped_ptr<Layer> l21(CreateColorLayer(SK_ColorMAGENTA,
1117 gfx::Rect(0, 0, 15, 15)));
1118 scoped_ptr<Layer> l12(CreateColorLayer(SK_ColorBLUE,
1119 gfx::Rect(10, 10, 25, 25)));
1121 base::FilePath ref_img1 =
1122 test_data_directory().AppendASCII("ModifyHierarchy1.png");
1123 base::FilePath ref_img2 =
1124 test_data_directory().AppendASCII("ModifyHierarchy2.png");
1125 SkBitmap bitmap;
1127 l0->Add(l11.get());
1128 l11->Add(l21.get());
1129 l0->Add(l12.get());
1130 DrawTree(l0.get());
1131 ReadPixels(&bitmap);
1132 ASSERT_FALSE(bitmap.empty());
1133 // WritePNGFile(bitmap, ref_img1);
1134 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1136 l0->StackAtTop(l11.get());
1137 DrawTree(l0.get());
1138 ReadPixels(&bitmap);
1139 ASSERT_FALSE(bitmap.empty());
1140 // WritePNGFile(bitmap, ref_img2);
1141 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1143 // should restore to original configuration
1144 l0->StackAbove(l12.get(), l11.get());
1145 DrawTree(l0.get());
1146 ReadPixels(&bitmap);
1147 ASSERT_FALSE(bitmap.empty());
1148 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1150 // l11 back to front
1151 l0->StackAtTop(l11.get());
1152 DrawTree(l0.get());
1153 ReadPixels(&bitmap);
1154 ASSERT_FALSE(bitmap.empty());
1155 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1157 // should restore to original configuration
1158 l0->StackAbove(l12.get(), l11.get());
1159 DrawTree(l0.get());
1160 ReadPixels(&bitmap);
1161 ASSERT_FALSE(bitmap.empty());
1162 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img1, cc::ExactPixelComparator(true)));
1164 // l11 back to front
1165 l0->StackAbove(l11.get(), l12.get());
1166 DrawTree(l0.get());
1167 ReadPixels(&bitmap);
1168 ASSERT_FALSE(bitmap.empty());
1169 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img2, cc::ExactPixelComparator(true)));
1172 // Opacity is rendered correctly.
1173 // Checks that modifying the hierarchy correctly affects final composite.
1174 TEST_F(LayerWithRealCompositorTest, Opacity) {
1175 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(50, 50));
1177 // l0
1178 // +-l11
1179 scoped_ptr<Layer> l0(CreateColorLayer(SK_ColorRED,
1180 gfx::Rect(0, 0, 50, 50)));
1181 scoped_ptr<Layer> l11(CreateColorLayer(SK_ColorGREEN,
1182 gfx::Rect(0, 0, 25, 25)));
1184 base::FilePath ref_img = test_data_directory().AppendASCII("Opacity.png");
1186 l11->SetOpacity(0.75);
1187 l0->Add(l11.get());
1188 DrawTree(l0.get());
1189 SkBitmap bitmap;
1190 ReadPixels(&bitmap);
1191 ASSERT_FALSE(bitmap.empty());
1192 // WritePNGFile(bitmap, ref_img);
1193 EXPECT_TRUE(MatchesPNGFile(bitmap, ref_img, cc::ExactPixelComparator(true)));
1196 namespace {
1198 class SchedulePaintLayerDelegate : public LayerDelegate {
1199 public:
1200 SchedulePaintLayerDelegate() : paint_count_(0), layer_(NULL) {}
1202 ~SchedulePaintLayerDelegate() override {}
1204 void set_layer(Layer* layer) {
1205 layer_ = layer;
1206 layer_->set_delegate(this);
1209 void SetSchedulePaintRect(const gfx::Rect& rect) {
1210 schedule_paint_rect_ = rect;
1213 int GetPaintCountAndClear() {
1214 int value = paint_count_;
1215 paint_count_ = 0;
1216 return value;
1219 const gfx::RectF& last_clip_rect() const { return last_clip_rect_; }
1221 private:
1222 // Overridden from LayerDelegate:
1223 void OnPaintLayer(gfx::Canvas* canvas) override {
1224 paint_count_++;
1225 if (!schedule_paint_rect_.IsEmpty()) {
1226 layer_->SchedulePaint(schedule_paint_rect_);
1227 schedule_paint_rect_ = gfx::Rect();
1229 SkRect sk_clip_rect;
1230 if (canvas->sk_canvas()->getClipBounds(&sk_clip_rect))
1231 last_clip_rect_ = gfx::SkRectToRectF(sk_clip_rect);
1234 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
1236 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
1238 base::Closure PrepareForLayerBoundsChange() override {
1239 return base::Closure();
1242 int paint_count_;
1243 Layer* layer_;
1244 gfx::Rect schedule_paint_rect_;
1245 gfx::RectF last_clip_rect_;
1247 DISALLOW_COPY_AND_ASSIGN(SchedulePaintLayerDelegate);
1250 } // namespace
1252 // Verifies that if SchedulePaint is invoked during painting the layer is still
1253 // marked dirty.
1254 TEST_F(LayerWithDelegateTest, SchedulePaintFromOnPaintLayer) {
1255 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorRED,
1256 gfx::Rect(0, 0, 500, 500)));
1257 SchedulePaintLayerDelegate child_delegate;
1258 scoped_ptr<Layer> child(CreateColorLayer(SK_ColorBLUE,
1259 gfx::Rect(0, 0, 200, 200)));
1260 child_delegate.set_layer(child.get());
1262 root->Add(child.get());
1264 SchedulePaintForLayer(root.get());
1265 DrawTree(root.get());
1266 child->SchedulePaint(gfx::Rect(0, 0, 20, 20));
1267 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1269 // Set a rect so that when OnPaintLayer() is invoked SchedulePaint is invoked
1270 // again.
1271 child_delegate.SetSchedulePaintRect(gfx::Rect(10, 10, 30, 30));
1272 WaitForCommit();
1273 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1275 // Because SchedulePaint() was invoked from OnPaintLayer() |child| should
1276 // still need to be painted.
1277 WaitForCommit();
1278 EXPECT_EQ(1, child_delegate.GetPaintCountAndClear());
1279 EXPECT_TRUE(child_delegate.last_clip_rect().Contains(
1280 gfx::Rect(10, 10, 30, 30)));
1283 TEST_F(LayerWithRealCompositorTest, ScaleUpDown) {
1284 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorWHITE,
1285 gfx::Rect(10, 20, 200, 220)));
1286 TestLayerDelegate root_delegate;
1287 root_delegate.AddColor(SK_ColorWHITE);
1288 root->set_delegate(&root_delegate);
1290 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorWHITE,
1291 gfx::Rect(10, 20, 140, 180)));
1292 TestLayerDelegate l1_delegate;
1293 l1_delegate.AddColor(SK_ColorWHITE);
1294 l1->set_delegate(&l1_delegate);
1296 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1297 GetCompositor()->SetRootLayer(root.get());
1298 root->Add(l1.get());
1299 WaitForDraw();
1301 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1302 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1303 gfx::Size cc_bounds_size = root->cc_layer()->bounds();
1304 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1305 cc_bounds_size = l1->cc_layer()->bounds();
1306 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1307 // No scale change, so no scale notification.
1308 EXPECT_EQ(0.0f, root_delegate.device_scale_factor());
1309 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1311 EXPECT_EQ("200x220", root_delegate.paint_size().ToString());
1312 EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1314 // Scale up to 2.0. Changing scale doesn't change the bounds in DIP.
1315 GetCompositor()->SetScaleAndSize(2.0f, gfx::Size(500, 500));
1316 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1317 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1318 // CC layer should still match the UI layer bounds.
1319 cc_bounds_size = root->cc_layer()->bounds();
1320 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1321 cc_bounds_size = l1->cc_layer()->bounds();
1322 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1323 // New scale factor must have been notified.
1324 EXPECT_EQ(2.0f, root_delegate.device_scale_factor());
1325 EXPECT_EQ(2.0f, l1_delegate.device_scale_factor());
1327 // Canvas size must have been scaled down up.
1328 WaitForDraw();
1329 EXPECT_EQ("400x440", root_delegate.paint_size().ToString());
1330 EXPECT_EQ("2.0 2.0", root_delegate.ToScaleString());
1331 EXPECT_EQ("280x360", l1_delegate.paint_size().ToString());
1332 EXPECT_EQ("2.0 2.0", l1_delegate.ToScaleString());
1334 // Scale down back to 1.0f.
1335 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1336 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1337 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1338 // CC layer should still match the UI layer bounds.
1339 cc_bounds_size = root->cc_layer()->bounds();
1340 EXPECT_EQ("200x220", cc_bounds_size.ToString());
1341 cc_bounds_size = l1->cc_layer()->bounds();
1342 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1343 // New scale factor must have been notified.
1344 EXPECT_EQ(1.0f, root_delegate.device_scale_factor());
1345 EXPECT_EQ(1.0f, l1_delegate.device_scale_factor());
1347 // Canvas size must have been scaled down too.
1348 WaitForDraw();
1349 EXPECT_EQ("200x220", root_delegate.paint_size().ToString());
1350 EXPECT_EQ("1.0 1.0", root_delegate.ToScaleString());
1351 EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1352 EXPECT_EQ("1.0 1.0", l1_delegate.ToScaleString());
1354 root_delegate.reset();
1355 l1_delegate.reset();
1356 // Just changing the size shouldn't notify the scale change nor
1357 // trigger repaint.
1358 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(1000, 1000));
1359 // No scale change, so no scale notification.
1360 EXPECT_EQ(0.0f, root_delegate.device_scale_factor());
1361 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1362 WaitForDraw();
1363 EXPECT_EQ("0x0", root_delegate.paint_size().ToString());
1364 EXPECT_EQ("0.0 0.0", root_delegate.ToScaleString());
1365 EXPECT_EQ("0x0", l1_delegate.paint_size().ToString());
1366 EXPECT_EQ("0.0 0.0", l1_delegate.ToScaleString());
1369 TEST_F(LayerWithRealCompositorTest, ScaleReparent) {
1370 scoped_ptr<Layer> root(CreateColorLayer(SK_ColorWHITE,
1371 gfx::Rect(10, 20, 200, 220)));
1372 scoped_ptr<Layer> l1(CreateColorLayer(SK_ColorWHITE,
1373 gfx::Rect(10, 20, 140, 180)));
1374 TestLayerDelegate l1_delegate;
1375 l1_delegate.AddColor(SK_ColorWHITE);
1376 l1->set_delegate(&l1_delegate);
1378 GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(500, 500));
1379 GetCompositor()->SetRootLayer(root.get());
1380 WaitForDraw();
1382 root->Add(l1.get());
1383 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1384 gfx::Size cc_bounds_size = l1->cc_layer()->bounds();
1385 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1386 EXPECT_EQ(0.0f, l1_delegate.device_scale_factor());
1388 WaitForDraw();
1389 EXPECT_EQ("140x180", l1_delegate.paint_size().ToString());
1390 EXPECT_EQ("1.0 1.0", l1_delegate.ToScaleString());
1392 // Remove l1 from root and change the scale.
1393 root->Remove(l1.get());
1394 EXPECT_EQ(NULL, l1->parent());
1395 EXPECT_EQ(NULL, l1->GetCompositor());
1396 GetCompositor()->SetScaleAndSize(2.0f, gfx::Size(500, 500));
1397 // Sanity check on root and l1.
1398 EXPECT_EQ("10,20 200x220", root->bounds().ToString());
1399 cc_bounds_size = l1->cc_layer()->bounds();
1400 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1402 root->Add(l1.get());
1403 EXPECT_EQ("10,20 140x180", l1->bounds().ToString());
1404 cc_bounds_size = l1->cc_layer()->bounds();
1405 EXPECT_EQ("140x180", cc_bounds_size.ToString());
1406 EXPECT_EQ(2.0f, l1_delegate.device_scale_factor());
1407 WaitForDraw();
1408 EXPECT_EQ("280x360", l1_delegate.paint_size().ToString());
1409 EXPECT_EQ("2.0 2.0", l1_delegate.ToScaleString());
1412 // Verifies that when changing bounds on a layer that is invisible, and then
1413 // made visible, the right thing happens:
1414 // - if just a move, then no painting should happen.
1415 // - if a resize, the layer should be repainted.
1416 TEST_F(LayerWithDelegateTest, SetBoundsWhenInvisible) {
1417 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1419 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1420 child->SetBounds(gfx::Rect(0, 0, 500, 500));
1421 DrawTreeLayerDelegate delegate;
1422 child->set_delegate(&delegate);
1423 root->Add(child.get());
1425 // Paint once for initial damage.
1426 child->SetVisible(true);
1427 DrawTree(root.get());
1429 // Reset into invisible state.
1430 child->SetVisible(false);
1431 DrawTree(root.get());
1432 delegate.Reset();
1434 // Move layer.
1435 child->SetBounds(gfx::Rect(200, 200, 500, 500));
1436 child->SetVisible(true);
1437 DrawTree(root.get());
1438 EXPECT_FALSE(delegate.painted());
1440 // Reset into invisible state.
1441 child->SetVisible(false);
1442 DrawTree(root.get());
1443 delegate.Reset();
1445 // Resize layer.
1446 child->SetBounds(gfx::Rect(200, 200, 400, 400));
1447 child->SetVisible(true);
1448 DrawTree(root.get());
1449 EXPECT_TRUE(delegate.painted());
1452 static scoped_ptr<cc::DelegatedFrameData> MakeFrameData(gfx::Size size) {
1453 scoped_ptr<cc::DelegatedFrameData> frame_data(new cc::DelegatedFrameData);
1454 scoped_ptr<cc::RenderPass> render_pass(cc::RenderPass::Create());
1455 render_pass->SetNew(
1456 cc::RenderPassId(1, 1), gfx::Rect(size), gfx::Rect(), gfx::Transform());
1457 frame_data->render_pass_list.push_back(render_pass.Pass());
1458 return frame_data.Pass();
1461 TEST_F(LayerWithDelegateTest, DelegatedLayer) {
1462 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1464 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1466 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1467 child->SetVisible(true);
1468 root->Add(child.get());
1469 DrawTree(root.get());
1471 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1472 new cc::DelegatedFrameResourceCollection;
1473 scoped_refptr<cc::DelegatedFrameProvider> frame_provider;
1475 // Content matches layer size.
1476 frame_provider = new cc::DelegatedFrameProvider(
1477 resource_collection.get(), MakeFrameData(gfx::Size(10, 10)));
1478 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1479 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1480 gfx::Size(10, 10).ToString());
1482 // Content larger than layer.
1483 child->SetBounds(gfx::Rect(0, 0, 5, 5));
1484 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1485 gfx::Size(5, 5).ToString());
1487 // Content smaller than layer.
1488 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1489 frame_provider = new cc::DelegatedFrameProvider(
1490 resource_collection.get(), MakeFrameData(gfx::Size(5, 5)));
1491 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(5, 5));
1492 EXPECT_EQ(child->cc_layer()->bounds().ToString(), gfx::Size(5, 5).ToString());
1494 // Hi-DPI content on low-DPI layer.
1495 frame_provider = new cc::DelegatedFrameProvider(
1496 resource_collection.get(), MakeFrameData(gfx::Size(20, 20)));
1497 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1498 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1499 gfx::Size(10, 10).ToString());
1501 // Hi-DPI content on hi-DPI layer.
1502 compositor()->SetScaleAndSize(2.f, gfx::Size(1000, 1000));
1503 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1504 gfx::Size(10, 10).ToString());
1506 // Low-DPI content on hi-DPI layer.
1507 frame_provider = new cc::DelegatedFrameProvider(
1508 resource_collection.get(), MakeFrameData(gfx::Size(10, 10)));
1509 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1510 EXPECT_EQ(child->cc_layer()->bounds().ToString(),
1511 gfx::Size(10, 10).ToString());
1514 TEST_F(LayerWithDelegateTest, ExternalContent) {
1515 scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
1516 scoped_ptr<Layer> child(CreateLayer(LAYER_SOLID_COLOR));
1518 child->SetBounds(gfx::Rect(0, 0, 10, 10));
1519 child->SetVisible(true);
1520 root->Add(child.get());
1522 // The layer is already showing solid color content, so the cc layer won't
1523 // change.
1524 scoped_refptr<cc::Layer> before = child->cc_layer();
1525 child->SetShowSolidColorContent();
1526 EXPECT_TRUE(child->cc_layer());
1527 EXPECT_EQ(before.get(), child->cc_layer());
1529 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1530 new cc::DelegatedFrameResourceCollection;
1531 scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
1532 new cc::DelegatedFrameProvider(resource_collection.get(),
1533 MakeFrameData(gfx::Size(10, 10)));
1535 // Showing delegated content changes the underlying cc layer.
1536 before = child->cc_layer();
1537 child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1538 EXPECT_TRUE(child->cc_layer());
1539 EXPECT_NE(before.get(), child->cc_layer());
1541 // Changing to painted content should change the underlying cc layer.
1542 before = child->cc_layer();
1543 child->SetShowSolidColorContent();
1544 EXPECT_TRUE(child->cc_layer());
1545 EXPECT_NE(before.get(), child->cc_layer());
1548 // Verifies that layer filters still attached after changing implementation
1549 // layer.
1550 TEST_F(LayerWithDelegateTest, LayerFiltersSurvival) {
1551 scoped_ptr<Layer> layer(CreateLayer(LAYER_TEXTURED));
1552 layer->SetBounds(gfx::Rect(0, 0, 10, 10));
1553 EXPECT_TRUE(layer->cc_layer());
1554 EXPECT_EQ(0u, layer->cc_layer()->filters().size());
1556 layer->SetLayerGrayscale(0.5f);
1557 EXPECT_EQ(layer->layer_grayscale(), 0.5f);
1558 EXPECT_EQ(1u, layer->cc_layer()->filters().size());
1560 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1561 new cc::DelegatedFrameResourceCollection;
1562 scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
1563 new cc::DelegatedFrameProvider(resource_collection.get(),
1564 MakeFrameData(gfx::Size(10, 10)));
1566 // Showing delegated content changes the underlying cc layer.
1567 scoped_refptr<cc::Layer> before = layer->cc_layer();
1568 layer->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1569 EXPECT_EQ(layer->layer_grayscale(), 0.5f);
1570 EXPECT_TRUE(layer->cc_layer());
1571 EXPECT_NE(before.get(), layer->cc_layer());
1572 EXPECT_EQ(1u, layer->cc_layer()->filters().size());
1575 // Tests Layer::AddThreadedAnimation and Layer::RemoveThreadedAnimation.
1576 TEST_F(LayerWithRealCompositorTest, AddRemoveThreadedAnimations) {
1577 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1578 scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
1579 scoped_ptr<Layer> l2(CreateLayer(LAYER_TEXTURED));
1581 l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1582 l2->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1584 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1586 // Trigger a threaded animation.
1587 l1->SetOpacity(0.5f);
1589 EXPECT_TRUE(l1->HasPendingThreadedAnimations());
1591 // Ensure we can remove a pending threaded animation.
1592 l1->GetAnimator()->StopAnimating();
1594 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1596 // Trigger another threaded animation.
1597 l1->SetOpacity(0.2f);
1599 EXPECT_TRUE(l1->HasPendingThreadedAnimations());
1601 root->Add(l1.get());
1602 GetCompositor()->SetRootLayer(root.get());
1604 // Now that l1 is part of a tree, it should have dispatched the pending
1605 // animation.
1606 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1608 // Ensure that l1 no longer holds on to animations.
1609 l1->SetOpacity(0.1f);
1610 EXPECT_FALSE(l1->HasPendingThreadedAnimations());
1612 // Ensure that adding a layer to an existing tree causes its pending
1613 // animations to get dispatched.
1614 l2->SetOpacity(0.5f);
1615 EXPECT_TRUE(l2->HasPendingThreadedAnimations());
1617 l1->Add(l2.get());
1618 EXPECT_FALSE(l2->HasPendingThreadedAnimations());
1621 // Tests that in-progress threaded animations complete when a Layer's
1622 // cc::Layer changes.
1623 TEST_F(LayerWithRealCompositorTest, SwitchCCLayerAnimations) {
1624 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1625 scoped_ptr<Layer> l1(CreateLayer(LAYER_TEXTURED));
1626 GetCompositor()->SetRootLayer(root.get());
1627 root->Add(l1.get());
1629 l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1631 EXPECT_FLOAT_EQ(l1->opacity(), 1.0f);
1633 // Trigger a threaded animation.
1634 l1->SetOpacity(0.5f);
1636 // Change l1's cc::Layer.
1637 l1->SwitchCCLayerForTest();
1639 // Ensure that the opacity animation completed.
1640 EXPECT_FLOAT_EQ(l1->opacity(), 0.5f);
1643 // Tests that the animators in the layer tree is added to the
1644 // animator-collection when the root-layer is set to the compositor.
1645 TEST_F(LayerWithDelegateTest, RootLayerAnimatorsInCompositor) {
1646 scoped_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR));
1647 scoped_ptr<Layer> child(CreateColorLayer(SK_ColorRED, gfx::Rect(10, 10)));
1648 child->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1649 child->SetOpacity(0.5f);
1650 root->Add(child.get());
1652 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1653 compositor()->SetRootLayer(root.get());
1654 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1657 // Tests that adding/removing a layer adds/removes the animator from its entire
1658 // subtree from the compositor's animator-collection.
1659 TEST_F(LayerWithDelegateTest, AddRemoveLayerUpdatesAnimatorsFromSubtree) {
1660 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1661 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1662 scoped_ptr<Layer> grandchild(CreateColorLayer(SK_ColorRED,
1663 gfx::Rect(10, 10)));
1664 root->Add(child.get());
1665 child->Add(grandchild.get());
1666 compositor()->SetRootLayer(root.get());
1668 grandchild->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1669 grandchild->SetOpacity(0.5f);
1670 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1672 root->Remove(child.get());
1673 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1675 root->Add(child.get());
1676 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1679 TEST_F(LayerWithDelegateTest, DestroyingLayerRemovesTheAnimatorFromCollection) {
1680 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1681 scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
1682 root->Add(child.get());
1683 compositor()->SetRootLayer(root.get());
1685 child->SetAnimator(LayerAnimator::CreateImplicitAnimator());
1686 child->SetOpacity(0.5f);
1687 EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
1689 child.reset();
1690 EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
1693 namespace {
1695 std::string Vector2dFTo100thPercisionString(const gfx::Vector2dF& vector) {
1696 return base::StringPrintf("%.2f %0.2f", vector.x(), vector.y());
1699 } // namespace
1701 TEST_F(LayerWithRealCompositorTest, SnapLayerToPixels) {
1702 scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
1703 scoped_ptr<Layer> c1(CreateLayer(LAYER_TEXTURED));
1704 scoped_ptr<Layer> c11(CreateLayer(LAYER_TEXTURED));
1706 GetCompositor()->SetScaleAndSize(1.25f, gfx::Size(100, 100));
1707 GetCompositor()->SetRootLayer(root.get());
1708 root->Add(c1.get());
1709 c1->Add(c11.get());
1711 root->SetBounds(gfx::Rect(0, 0, 100, 100));
1712 c1->SetBounds(gfx::Rect(1, 1, 10, 10));
1713 c11->SetBounds(gfx::Rect(1, 1, 10, 10));
1714 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
1715 // 0.5 at 1.25 scale : (1 - 0.25 + 0.25) / 1.25 = 0.4
1716 EXPECT_EQ("0.40 0.40",
1717 Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
1719 GetCompositor()->SetScaleAndSize(1.5f, gfx::Size(100, 100));
1720 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
1721 // c11 must already be aligned at 1.5 scale.
1722 EXPECT_EQ("0.00 0.00",
1723 Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
1725 c11->SetBounds(gfx::Rect(2, 2, 10, 10));
1726 SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
1727 // c11 is now off the pixel.
1728 // 0.5 / 1.5 = 0.333...
1729 EXPECT_EQ("0.33 0.33",
1730 Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
1733 class FrameDamageCheckingDelegate : public TestLayerDelegate {
1734 public:
1735 FrameDamageCheckingDelegate() : delegated_frame_damage_called_(false) {}
1737 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {
1738 delegated_frame_damage_called_ = true;
1739 delegated_frame_damage_rect_ = damage_rect_in_dip;
1742 const gfx::Rect& delegated_frame_damage_rect() const {
1743 return delegated_frame_damage_rect_;
1745 bool delegated_frame_damage_called() const {
1746 return delegated_frame_damage_called_;
1749 private:
1750 gfx::Rect delegated_frame_damage_rect_;
1751 bool delegated_frame_damage_called_;
1753 DISALLOW_COPY_AND_ASSIGN(FrameDamageCheckingDelegate);
1756 TEST(LayerDelegateTest, DelegatedFrameDamage) {
1757 scoped_ptr<Layer> layer(new Layer(LAYER_TEXTURED));
1758 gfx::Rect damage_rect(2, 1, 5, 3);
1760 FrameDamageCheckingDelegate delegate;
1761 layer->set_delegate(&delegate);
1762 scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
1763 new cc::DelegatedFrameResourceCollection;
1764 scoped_refptr<cc::DelegatedFrameProvider> frame_provider(
1765 new cc::DelegatedFrameProvider(resource_collection.get(),
1766 MakeFrameData(gfx::Size(10, 10))));
1767 layer->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
1769 EXPECT_FALSE(delegate.delegated_frame_damage_called());
1770 layer->OnDelegatedFrameDamage(damage_rect);
1771 EXPECT_TRUE(delegate.delegated_frame_damage_called());
1772 EXPECT_EQ(damage_rect, delegate.delegated_frame_damage_rect());
1775 } // namespace ui