OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "ui/views/controls/button/label_button.h" |
| 6 |
| 7 #include "base/strings/utf_string_conversions.h" |
| 8 #include "base/test/perf_time_logger.h" |
| 9 #include "cc/playback/display_item_list.h" |
| 10 #include "cc/playback/display_item_list_settings.h" |
| 11 #include "ui/compositor/paint_context.h" |
| 12 #include "ui/views/test/widget_test.h" |
| 13 |
| 14 namespace views { |
| 15 namespace { |
| 16 |
| 17 const int kWarmupIterations = 20; |
| 18 const int kScaleFactor = 2.0f; // Test HiDPI. |
| 19 |
| 20 class LabelButtonPerfTest : public test::WidgetTest { |
| 21 public: |
| 22 LabelButtonPerfTest() {} |
| 23 |
| 24 // Body of the test after a button has been created. Goal is to simulate the |
| 25 // impact of adding one additional button on the time to first paint a dialog. |
| 26 void PostCreateTestBody(const ui::PaintContext& paint_context, View* view) { |
| 27 view->SizeToPreferredSize(); |
| 28 widget_->GetContentsView()->AddChildView(view); |
| 29 widget_->GetContentsView()->Layout(); |
| 30 // Paint into a new canvas. This gets adopted by the View's PaintCache to |
| 31 // emulate a "first" paint scenario. Paints the root view, so that the |
| 32 // PaintContext can be reused. |
| 33 widget_->GetRootView()->Paint(paint_context); |
| 34 } |
| 35 |
| 36 void RunViewInitPaintTest(const char* test_name, |
| 37 const base::Callback<View*()>& factory, |
| 38 int perf_test_iterations) { |
| 39 // Create a template view to determine size and ensure resources are loaded |
| 40 // for the given scale factor. |
| 41 gfx::Rect canvas_rect; |
| 42 { |
| 43 const gfx::Rect template_rect(100, 100); |
| 44 scoped_refptr<cc::DisplayItemList> list = cc::DisplayItemList::Create( |
| 45 template_rect, cc::DisplayItemListSettings()); |
| 46 ui::PaintContext paint_context(list.get(), kScaleFactor, template_rect, |
| 47 template_rect); |
| 48 scoped_ptr<View> template_view(factory.Run()); |
| 49 PostCreateTestBody(paint_context, template_view.get()); |
| 50 canvas_rect = template_view->bounds(); |
| 51 } |
| 52 |
| 53 // Sanity check to ensure something is happening. |
| 54 EXPECT_LT(10, canvas_rect.width()); |
| 55 EXPECT_LT(10, canvas_rect.height()); |
| 56 |
| 57 // Repaint with the same PaintContext each time. |
| 58 scoped_refptr<cc::DisplayItemList> list = |
| 59 cc::DisplayItemList::Create(canvas_rect, cc::DisplayItemListSettings()); |
| 60 ui::PaintContext paint_context(list.get(), kScaleFactor, canvas_rect, |
| 61 canvas_rect); |
| 62 |
| 63 for (int iteration = 0; iteration < kWarmupIterations; ++iteration) { |
| 64 scoped_ptr<View> view(factory.Run()); |
| 65 PostCreateTestBody(paint_context, view.get()); |
| 66 } |
| 67 |
| 68 base::PerfTimeLogger timer(test_name); |
| 69 for (int iteration = 0; iteration < perf_test_iterations; ++iteration) { |
| 70 scoped_ptr<View> view(factory.Run()); |
| 71 PostCreateTestBody(paint_context, view.get()); |
| 72 // scoped_ptr destructor removes the button from the hierarchy. |
| 73 } |
| 74 // PerfTimeLogger destructor logs duration. |
| 75 } |
| 76 |
| 77 // testing::Test: |
| 78 void SetUp() override { |
| 79 ViewsTestBase::SetUp(); |
| 80 // Some initialization (e.g. for theming) does not occur until a view is |
| 81 // actually added to a widget. Create a widget for that, but don't ever show |
| 82 // it nor paint it. |
| 83 widget_ = CreateTopLevelPlatformWidget(); |
| 84 widget_->SetSize(gfx::Size(200, 200)); |
| 85 widget_->Show(); |
| 86 } |
| 87 |
| 88 void TearDown() override { |
| 89 widget_->CloseNow(); |
| 90 ViewsTestBase::TearDown(); |
| 91 } |
| 92 |
| 93 protected: |
| 94 Widget* widget_ = nullptr; |
| 95 |
| 96 private: |
| 97 DISALLOW_COPY_AND_ASSIGN(LabelButtonPerfTest); |
| 98 }; |
| 99 |
| 100 // Factory functions for the test. Try to mimic the manner by which Views are |
| 101 // are typically created in client code. |
| 102 View* CreateTextbutton(const base::string16& text) { |
| 103 return new LabelButton(nullptr, text); |
| 104 } |
| 105 |
| 106 View* CreateButton(const base::string16& text) { |
| 107 LabelButton* button = new LabelButton(nullptr, text); |
| 108 button->SetStyle(Button::STYLE_BUTTON); |
| 109 return button; |
| 110 } |
| 111 |
| 112 } // namespace |
| 113 |
| 114 // Performance tests for initializing a LabelButton, adding it to a View |
| 115 // hierarchy, then performing a "first" paint. Ballpark figures are given for |
| 116 // the duration of a single iteration on a z620 running Linux. |
| 117 |
| 118 // Test STYLE_TEXTBUTTON with no text. Ballpark: 1ms debug 0.3ms release. |
| 119 TEST_F(LabelButtonPerfTest, InitAndPaintTextbuttonNoText) { |
| 120 RunViewInitPaintTest("views_label_button_text_button_no_text_1000", |
| 121 base::Bind(&CreateTextbutton, base::string16()), |
| 122 1000); |
| 123 } |
| 124 |
| 125 // Test STYLE_TEXTBUTTON with the label "abc". Ballpark: 8ms debug, 7ms release. |
| 126 TEST_F(LabelButtonPerfTest, InitAndPaintTextbuttonAbcText) { |
| 127 RunViewInitPaintTest( |
| 128 "views_label_button_text_button_abc_text_100", |
| 129 base::Bind(&CreateTextbutton, base::ASCIIToUTF16("abc")), |
| 130 100); |
| 131 } |
| 132 |
| 133 // Test STYLE_BUTTON with no text. Ballpark: 2.5ms debug 1ms release. |
| 134 TEST_F(LabelButtonPerfTest, InitAndPaintButtonNoText) { |
| 135 RunViewInitPaintTest("views_label_button_button_no_text_1000", |
| 136 base::Bind(&CreateButton, base::string16()), |
| 137 1000); |
| 138 } |
| 139 |
| 140 // Test STYLE_BUTTON with the label "abc". Ballpark: 12ms debug, 9ms release. |
| 141 TEST_F(LabelButtonPerfTest, InitAndPaintButtonAbcText) { |
| 142 RunViewInitPaintTest("views_label_button_button_abc_text_100", |
| 143 base::Bind(&CreateButton, base::ASCIIToUTF16("abc")), |
| 144 100); |
| 145 } |
| 146 |
| 147 } // namespace views |
OLD | NEW |