OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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/paint_info.h" |
| 6 |
| 7 #include <vector> |
| 8 |
| 9 #include "base/macros.h" |
| 10 #include "base/memory/ref_counted.h" |
| 11 #include "cc/base/region.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" |
| 13 #include "ui/compositor/compositor_switches.h" |
| 14 #include "ui/compositor/paint_context.h" |
| 15 #include "ui/gfx/geometry/rect.h" |
| 16 #include "ui/gfx/geometry/size.h" |
| 17 |
| 18 namespace views { |
| 19 namespace { |
| 20 |
| 21 using PaintInfos = std::vector<std::unique_ptr<PaintInfo>>; |
| 22 |
| 23 // Device scale factors |
| 24 constexpr float DSF100 = 1.f; |
| 25 constexpr float DSF125 = 1.25f; |
| 26 constexpr float DSF150 = 1.5f; |
| 27 constexpr float DSF160 = 1.6f; |
| 28 constexpr float DSF166 = 1.66f; |
| 29 |
| 30 const std::vector<float> kDsfList = {DSF100, DSF125, DSF150, DSF160, DSF166}; |
| 31 |
| 32 constexpr gfx::Size kLayerSize(123, 456); |
| 33 |
| 34 // ___________ |
| 35 // | 1 | |
| 36 // |___________| |
| 37 // | 3 | 4 | 5 | <-- 2 (encapsulates 3, 4 and 5) |
| 38 // |___|___|___| |
| 39 // | 7 | 8 | <-- 6 (encapsulates 7 and 8) |
| 40 // |_______|___| |
| 41 // |
| 42 // |r_0| encapsulates 1, 2 and 6. |
| 43 const gfx::Rect r_0(kLayerSize); |
| 44 |
| 45 constexpr gfx::Rect r_1(0, 0, 123, 152); |
| 46 |
| 47 constexpr gfx::Rect r_2(0, 152, 123, 152); |
| 48 constexpr gfx::Rect r_3(0, 0, 41, 152); |
| 49 constexpr gfx::Rect r_4(41, 0, 41, 152); |
| 50 constexpr gfx::Rect r_5(82, 0, 41, 152); |
| 51 |
| 52 constexpr gfx::Rect r_6(0, 304, 123, 152); |
| 53 constexpr gfx::Rect r_7(0, 0, 82, 152); |
| 54 constexpr gfx::Rect r_8(82, 0, 41, 152); |
| 55 |
| 56 // Verifies that the child recording bounds completely cover the parent |
| 57 // recording bounds. |
| 58 void VerifyChildBoundsCoversParent(const PaintInfo* parent_paint_info, |
| 59 const std::vector<PaintInfo*>& info_list) { |
| 60 cc::Region remaining(gfx::Rect(parent_paint_info->paint_recording_size())); |
| 61 int times_empty = 0; |
| 62 for (auto* const paint_info : info_list) { |
| 63 const gfx::Rect& child_recording_bounds = |
| 64 paint_info->paint_recording_bounds() - |
| 65 parent_paint_info->paint_recording_bounds().OffsetFromOrigin(); |
| 66 EXPECT_TRUE(remaining.Contains(child_recording_bounds)) |
| 67 << "Remaining: " << remaining.ToString() |
| 68 << " paint recording bounds: " << child_recording_bounds.ToString(); |
| 69 remaining.Subtract(child_recording_bounds); |
| 70 times_empty += remaining.IsEmpty(); |
| 71 } |
| 72 EXPECT_EQ(times_empty, 1); |
| 73 } |
| 74 |
| 75 void VerifyPixelCanvasCornerScaling(const PaintInfos& info_list) { |
| 76 // child 1, child 2 and child 6 should completely cover child 0. |
| 77 std::vector<PaintInfo*> child_info_list; |
| 78 child_info_list.push_back(info_list[1].get()); |
| 79 child_info_list.push_back(info_list[2].get()); |
| 80 child_info_list.push_back(info_list[6].get()); |
| 81 VerifyChildBoundsCoversParent(info_list[0].get(), child_info_list); |
| 82 child_info_list.clear(); |
| 83 |
| 84 // Child 3,4 and 5 should completely cover child 2. |
| 85 child_info_list.push_back(info_list[3].get()); |
| 86 child_info_list.push_back(info_list[4].get()); |
| 87 child_info_list.push_back(info_list[5].get()); |
| 88 VerifyChildBoundsCoversParent(info_list[2].get(), child_info_list); |
| 89 child_info_list.clear(); |
| 90 |
| 91 // Child 7 and 8 should completely cover child 6. |
| 92 child_info_list.push_back(info_list[7].get()); |
| 93 child_info_list.push_back(info_list[8].get()); |
| 94 VerifyChildBoundsCoversParent(info_list[6].get(), child_info_list); |
| 95 child_info_list.clear(); |
| 96 } |
| 97 |
| 98 void VerifyPixelSizesAreSameAsDIPSize(const PaintInfos& info_list) { |
| 99 EXPECT_EQ(info_list[0]->paint_recording_size(), r_0.size()); |
| 100 |
| 101 EXPECT_EQ(info_list[1]->paint_recording_size(), r_1.size()); |
| 102 |
| 103 EXPECT_EQ(info_list[2]->paint_recording_size(), r_2.size()); |
| 104 EXPECT_EQ(info_list[3]->paint_recording_size(), r_3.size()); |
| 105 EXPECT_EQ(info_list[4]->paint_recording_size(), r_4.size()); |
| 106 EXPECT_EQ(info_list[5]->paint_recording_size(), r_5.size()); |
| 107 |
| 108 EXPECT_EQ(info_list[6]->paint_recording_size(), r_6.size()); |
| 109 EXPECT_EQ(info_list[7]->paint_recording_size(), r_7.size()); |
| 110 EXPECT_EQ(info_list[8]->paint_recording_size(), r_8.size()); |
| 111 } |
| 112 |
| 113 } // namespace |
| 114 |
| 115 class PaintInfoTest : public ::testing::Test { |
| 116 public: |
| 117 PaintInfoTest() {} |
| 118 |
| 119 ~PaintInfoTest() override {} |
| 120 |
| 121 // ___________ |
| 122 // | 1 | |
| 123 // |___________| |
| 124 // | 3 | 4 | 5 | <-- 2 (encapsulates 3, 4 and 5) |
| 125 // |___|___|___| |
| 126 // | 7 | 8 | <-- 6 (encapsulates 7 and 8) |
| 127 // |_______|___| |
| 128 // |
| 129 // |r_0| encapsulates 1, 2 and 6. |
| 130 // |
| 131 // Returns the following arrangement of paint recording bounds for the given |
| 132 // |dsf| |
| 133 PaintInfos GetPaintInfoSetup(const ui::PaintContext& context) { |
| 134 PaintInfos info_list(9); |
| 135 |
| 136 info_list[0].reset(new PaintInfo(context, kLayerSize)); |
| 137 |
| 138 info_list[1].reset(new PaintInfo(*info_list[0], r_1, r_0.size(), |
| 139 PaintInfo::ScaleType::kScaleToFit)); |
| 140 |
| 141 info_list[2].reset(new PaintInfo(*info_list[0], r_2, r_0.size(), |
| 142 PaintInfo::ScaleType::kScaleToFit)); |
| 143 info_list[3].reset(new PaintInfo(*info_list[2], r_3, r_2.size(), |
| 144 PaintInfo::ScaleType::kScaleToFit)); |
| 145 info_list[4].reset(new PaintInfo(*info_list[2], r_4, r_2.size(), |
| 146 PaintInfo::ScaleType::kScaleToFit)); |
| 147 info_list[5].reset(new PaintInfo(*info_list[2], r_5, r_2.size(), |
| 148 PaintInfo::ScaleType::kScaleToFit)); |
| 149 |
| 150 info_list[6].reset(new PaintInfo(*info_list[0], r_6, r_0.size(), |
| 151 PaintInfo::ScaleType::kScaleToFit)); |
| 152 info_list[7].reset(new PaintInfo(*info_list[6], r_7, r_6.size(), |
| 153 PaintInfo::ScaleType::kScaleToFit)); |
| 154 info_list[8].reset(new PaintInfo(*info_list[6], r_8, r_6.size(), |
| 155 PaintInfo::ScaleType::kScaleToFit)); |
| 156 |
| 157 return info_list; |
| 158 } |
| 159 |
| 160 void VerifyInvalidationRects(float dsf, bool pixel_canvas_enabled) { |
| 161 std::vector<gfx::Rect> invalidation_rects = { |
| 162 gfx::Rect(0, 0, 123, 41), // Intersects with 0 & 1. |
| 163 gfx::Rect(0, 76, 60, 152), // Intersects 0, 1, 2, 3 & 4. |
| 164 gfx::Rect(41, 152, 41, 152), // Intersects with 0, 2 & 4. |
| 165 gfx::Rect(80, 320, 4, 4), // Intersects with 0, 6, 7 & 8. |
| 166 gfx::Rect(40, 151, 43, 154), // Intersects all |
| 167 gfx::Rect(82, 304, 1, 1), // Intersects with 0, 6 & 8. |
| 168 gfx::Rect(81, 303, 2, 2) // Intersects with 0, 2, 4, 5, 6, 7, 8 |
| 169 }; |
| 170 |
| 171 std::vector<std::vector<int>> repaint_indices = { |
| 172 std::vector<int>{0, 1}, |
| 173 std::vector<int>{0, 1, 2, 3, 4}, |
| 174 std::vector<int>{0, 2, 4}, |
| 175 std::vector<int>{0, 6, 7, 8}, |
| 176 std::vector<int>{0, 1, 2, 3, 4, 5, 6, 7, 8}, |
| 177 std::vector<int>{0, 6, 8}, |
| 178 std::vector<int>{0, 2, 4, 5, 6, 7, 8}}; |
| 179 |
| 180 PaintInfos info_list; |
| 181 |
| 182 EXPECT_EQ(repaint_indices.size(), invalidation_rects.size()); |
| 183 for (size_t i = 0; i < invalidation_rects.size(); i++) { |
| 184 ui::PaintContext context(nullptr, dsf, invalidation_rects[i], |
| 185 pixel_canvas_enabled); |
| 186 info_list = GetPaintInfoSetup(context); |
| 187 for (size_t j = 0; j < repaint_indices[i].size(); j++) { |
| 188 EXPECT_TRUE( |
| 189 info_list[repaint_indices[i][j]]->context().IsRectInvalid(gfx::Rect( |
| 190 info_list[repaint_indices[i][j]]->paint_recording_size()))); |
| 191 } |
| 192 info_list.clear(); |
| 193 } |
| 194 } |
| 195 }; |
| 196 |
| 197 TEST_F(PaintInfoTest, CornerScalingPixelCanvasEnabled) { |
| 198 PaintInfos info_list; |
| 199 for (float dsf : kDsfList) { |
| 200 ui::PaintContext context(nullptr, dsf, gfx::Rect(), true); |
| 201 info_list = GetPaintInfoSetup(context); |
| 202 VerifyPixelCanvasCornerScaling(info_list); |
| 203 info_list.clear(); |
| 204 } |
| 205 |
| 206 // More accurate testing for 1.25 dsf |
| 207 ui::PaintContext context(nullptr, DSF125, gfx::Rect(), true); |
| 208 info_list = GetPaintInfoSetup(context); |
| 209 VerifyPixelCanvasCornerScaling(info_list); |
| 210 EXPECT_EQ(info_list[0]->paint_recording_size(), gfx::Size(154, 570)); |
| 211 |
| 212 EXPECT_EQ(info_list[1]->paint_recording_size(), gfx::Size(154, 190)); |
| 213 |
| 214 EXPECT_EQ(info_list[2]->paint_recording_bounds(), |
| 215 gfx::Rect(0, 190, 154, 190)); |
| 216 EXPECT_EQ(info_list[3]->paint_recording_size(), gfx::Size(51, 190)); |
| 217 EXPECT_EQ(info_list[4]->paint_recording_bounds(), |
| 218 gfx::Rect(51, 190, 52, 190)); |
| 219 EXPECT_EQ(info_list[5]->paint_recording_bounds(), |
| 220 gfx::Rect(103, 190, 51, 190)); |
| 221 |
| 222 EXPECT_EQ(info_list[6]->paint_recording_bounds(), |
| 223 gfx::Rect(0, 380, 154, 190)); |
| 224 EXPECT_EQ(info_list[7]->paint_recording_size(), gfx::Size(103, 190)); |
| 225 EXPECT_EQ(info_list[8]->paint_recording_bounds(), |
| 226 gfx::Rect(103, 380, 51, 190)); |
| 227 } |
| 228 |
| 229 TEST_F(PaintInfoTest, ScalingWithPixelCanvasDisabled) { |
| 230 for (float dsf : kDsfList) { |
| 231 ui::PaintContext context(nullptr, dsf, gfx::Rect(), false); |
| 232 PaintInfos info_list = GetPaintInfoSetup(context); |
| 233 VerifyPixelCanvasCornerScaling(info_list); |
| 234 VerifyPixelSizesAreSameAsDIPSize(info_list); |
| 235 info_list.clear(); |
| 236 } |
| 237 } |
| 238 |
| 239 TEST_F(PaintInfoTest, Invalidation) { |
| 240 for (float dsf : kDsfList) { |
| 241 VerifyInvalidationRects(dsf, false); |
| 242 VerifyInvalidationRects(dsf, true); |
| 243 } |
| 244 } |
| 245 |
| 246 } // namespace views |
OLD | NEW |