blob: ce155fde71403ca299dbcfc206724b01b87ca924 [file] [log] [blame]
[email protected]f95805472013-05-25 04:31:191// Copyright (c) 2013 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/snapshot/snapshot.h"
6
avi9c81217b2015-12-24 23:40:057#include <stddef.h>
8#include <stdint.h>
9
[email protected]c051d5a52014-01-08 23:54:5110#include "base/bind.h"
avi9c81217b2015-12-24 23:40:0511#include "base/macros.h"
Gabriel Charette078e3662017-08-28 22:59:0412#include "base/run_loop.h"
jonross1ec7d992018-08-31 03:55:5413#include "base/test/scoped_task_environment.h"
[email protected]c051d5a52014-01-08 23:54:5114#include "base/test/test_simple_task_runner.h"
Nico Webera79a1192018-06-13 14:13:2815#include "base/win/windows_version.h"
16#include "build/build_config.h"
[email protected]f95805472013-05-25 04:31:1917#include "testing/gtest/include/gtest/gtest.h"
fmalita577ac192017-01-10 15:33:0318#include "third_party/skia/include/core/SkPixelRef.h"
[email protected]4cc33f402014-03-26 15:33:3519#include "ui/aura/test/aura_test_helper.h"
[email protected]f95805472013-05-25 04:31:1920#include "ui/aura/test/test_screen.h"
21#include "ui/aura/test/test_window_delegate.h"
22#include "ui/aura/test/test_windows.h"
23#include "ui/aura/window.h"
[email protected]fcc51c952014-02-21 21:31:2624#include "ui/aura/window_event_dispatcher.h"
[email protected]fa69f2b62014-05-22 21:47:5825#include "ui/compositor/compositor.h"
[email protected]f95805472013-05-25 04:31:1926#include "ui/compositor/layer.h"
danakj533d7342015-04-07 22:32:2927#include "ui/compositor/paint_recorder.h"
[email protected]b58081d2014-01-24 10:13:5128#include "ui/compositor/test/draw_waiter_for_test.h"
Mohsen Izadib3710182019-04-30 04:57:3529#include "ui/compositor/test/test_context_factories.h"
[email protected]f95805472013-05-25 04:31:1930#include "ui/gfx/canvas.h"
tfarina3b0452d2014-12-31 15:20:0931#include "ui/gfx/geometry/rect.h"
tfarinaebe974f02015-01-03 04:25:3232#include "ui/gfx/geometry/size_conversions.h"
[email protected]f95805472013-05-25 04:31:1933#include "ui/gfx/image/image.h"
[email protected]f95805472013-05-25 04:31:1934#include "ui/gfx/transform.h"
35#include "ui/gl/gl_implementation.h"
[email protected]f3b1efd2014-04-30 04:48:2036#include "ui/wm/core/default_activation_client.h"
[email protected]f95805472013-05-25 04:31:1937
38namespace ui {
39namespace {
[email protected]7cfd3d22014-01-24 07:26:1540
41SkColor GetExpectedColorForPoint(int x, int y) {
42 return SkColorSetRGB(std::min(x, 255), std::min(y, 255), 0);
43}
[email protected]f95805472013-05-25 04:31:1944
45// Paint simple rectangle on the specified aura window.
46class TestPaintingWindowDelegate : public aura::test::TestWindowDelegate {
47 public:
48 explicit TestPaintingWindowDelegate(const gfx::Size& window_size)
49 : window_size_(window_size) {
50 }
51
dchengbc07fa02014-10-29 20:07:2452 ~TestPaintingWindowDelegate() override {}
[email protected]f95805472013-05-25 04:31:1953
danakj85d970e2015-04-04 00:15:2454 void OnPaint(const ui::PaintContext& context) override {
weiliangca032f93b2015-07-13 22:39:4755 ui::PaintRecorder recorder(context, window_size_);
[email protected]7cfd3d22014-01-24 07:26:1556 for (int y = 0; y < window_size_.height(); ++y) {
danakj85d970e2015-04-04 00:15:2457 for (int x = 0; x < window_size_.width(); ++x) {
danakj533d7342015-04-07 22:32:2958 recorder.canvas()->FillRect(gfx::Rect(x, y, 1, 1),
59 GetExpectedColorForPoint(x, y));
danakj85d970e2015-04-04 00:15:2460 }
[email protected]7cfd3d22014-01-24 07:26:1561 }
[email protected]f95805472013-05-25 04:31:1962 }
63
64 private:
65 gfx::Size window_size_;
66
67 DISALLOW_COPY_AND_ASSIGN(TestPaintingWindowDelegate);
68};
69
[email protected]7cfd3d22014-01-24 07:26:1570size_t GetFailedPixelsCountWithScaleFactor(const gfx::Image& image,
71 int scale_factor) {
[email protected]f95805472013-05-25 04:31:1972 const SkBitmap* bitmap = image.ToSkBitmap();
avi9c81217b2015-12-24 23:40:0573 uint32_t* bitmap_data =
74 reinterpret_cast<uint32_t*>(bitmap->pixelRef()->pixels());
[email protected]f95805472013-05-25 04:31:1975 size_t result = 0;
[email protected]7cfd3d22014-01-24 07:26:1576 for (int y = 0; y < bitmap->height(); y += scale_factor) {
77 for (int x = 0; x < bitmap->width(); x += scale_factor) {
78 if (static_cast<SkColor>(bitmap_data[x + y * bitmap->width()]) !=
79 GetExpectedColorForPoint(x / scale_factor, y / scale_factor)) {
80 ++result;
81 }
82 }
[email protected]f95805472013-05-25 04:31:1983 }
84 return result;
85}
86
[email protected]7cfd3d22014-01-24 07:26:1587size_t GetFailedPixelsCount(const gfx::Image& image) {
88 return GetFailedPixelsCountWithScaleFactor(image, 1);
89}
90
[email protected]f95805472013-05-25 04:31:1991} // namespace
92
[email protected]43ea25e32014-01-16 22:36:1593class SnapshotAuraTest : public testing::Test {
[email protected]f95805472013-05-25 04:31:1994 public:
95 SnapshotAuraTest() {}
dchengbc07fa02014-10-29 20:07:2496 ~SnapshotAuraTest() override {}
[email protected]f95805472013-05-25 04:31:1997
dchengbc07fa02014-10-29 20:07:2498 void SetUp() override {
[email protected]f95805472013-05-25 04:31:1999 testing::Test::SetUp();
[email protected]380a8bdf2014-02-20 19:02:54100
jonross1ec7d992018-08-31 03:55:54101 scoped_task_environment_ =
102 std::make_unique<base::test::ScopedTaskEnvironment>(
103 base::test::ScopedTaskEnvironment::MainThreadType::UI);
104
[email protected]380a8bdf2014-02-20 19:02:54105 // The ContextFactory must exist before any Compositors are created.
106 // Snapshot test tests real drawing and readback, so needs pixel output.
Mohsen Izadib3710182019-04-30 04:57:35107 const bool enable_pixel_output = true;
108 context_factories_ =
109 std::make_unique<ui::TestContextFactories>(enable_pixel_output);
fsamuela0bcfe12016-12-14 06:21:49110
Mohsen Izadib3710182019-04-30 04:57:35111 helper_ = std::make_unique<aura::test::AuraTestHelper>();
112 helper_->SetUp(context_factories_->GetContextFactory(),
113 context_factories_->GetContextFactoryPrivate());
[email protected]f3b1efd2014-04-30 04:48:20114 new ::wm::DefaultActivationClient(helper_->root_window());
[email protected]f95805472013-05-25 04:31:19115 }
116
dchengbc07fa02014-10-29 20:07:24117 void TearDown() override {
[email protected]f95805472013-05-25 04:31:19118 test_window_.reset();
119 delegate_.reset();
120 helper_->RunAllPendingInMessageLoop();
121 helper_->TearDown();
Mohsen Izadib3710182019-04-30 04:57:35122 context_factories_.reset();
jonross1ec7d992018-08-31 03:55:54123 scoped_task_environment_.reset();
[email protected]f95805472013-05-25 04:31:19124 testing::Test::TearDown();
125 }
126
127 protected:
128 aura::Window* test_window() { return test_window_.get(); }
[email protected]688c225e2013-11-10 06:16:08129 aura::Window* root_window() { return helper_->root_window(); }
[email protected]f95805472013-05-25 04:31:19130 aura::TestScreen* test_screen() { return helper_->test_screen(); }
131
132 void WaitForDraw() {
[email protected]a06955222014-03-10 22:47:32133 helper_->host()->compositor()->ScheduleDraw();
starazb14cc10cc2017-04-13 18:06:39134 ui::DrawWaiterForTest::WaitForCompositingEnded(
weiliangc5efa0a12015-01-29 19:56:46135 helper_->host()->compositor());
[email protected]f95805472013-05-25 04:31:19136 }
137
138 void SetupTestWindow(const gfx::Rect& window_bounds) {
139 delegate_.reset(new TestPaintingWindowDelegate(window_bounds.size()));
140 test_window_.reset(aura::test::CreateTestWindowWithDelegate(
141 delegate_.get(), 0, window_bounds, root_window()));
142 }
143
144 gfx::Image GrabSnapshotForTestWindow() {
[email protected]c051d5a52014-01-08 23:54:51145 gfx::Rect source_rect(test_window_->bounds().size());
[email protected]f51a7122014-06-12 10:06:51146 aura::Window::ConvertRectToTarget(
147 test_window(), root_window(), &source_rect);
[email protected]c051d5a52014-01-08 23:54:51148
[email protected]c051d5a52014-01-08 23:54:51149 scoped_refptr<SnapshotHolder> holder(new SnapshotHolder);
150 ui::GrabWindowSnapshotAsync(
eseckler7233c1a72017-01-25 15:07:54151 root_window(), source_rect,
[email protected]c051d5a52014-01-08 23:54:51152 base::Bind(&SnapshotHolder::SnapshotCallback, holder));
153
eseckler7233c1a72017-01-25 15:07:54154 holder->WaitForSnapshot();
155 DCHECK(holder->completed());
156 return holder->image();
[email protected]f95805472013-05-25 04:31:19157 }
158
159 private:
[email protected]c051d5a52014-01-08 23:54:51160 class SnapshotHolder : public base::RefCountedThreadSafe<SnapshotHolder> {
161 public:
162 SnapshotHolder() : completed_(false) {}
163
Xiaohui Chen5913da32017-11-16 18:10:09164 void SnapshotCallback(gfx::Image image) {
[email protected]c051d5a52014-01-08 23:54:51165 DCHECK(!completed_);
eseckler7233c1a72017-01-25 15:07:54166 image_ = image;
[email protected]c051d5a52014-01-08 23:54:51167 completed_ = true;
eseckler7233c1a72017-01-25 15:07:54168 run_loop_.Quit();
[email protected]c051d5a52014-01-08 23:54:51169 }
eseckler7233c1a72017-01-25 15:07:54170 void WaitForSnapshot() { run_loop_.Run(); }
Xiaohui Chen5913da32017-11-16 18:10:09171 bool completed() const { return completed_; }
[email protected]c051d5a52014-01-08 23:54:51172 const gfx::Image& image() const { return image_; }
173
174 private:
175 friend class base::RefCountedThreadSafe<SnapshotHolder>;
176
177 virtual ~SnapshotHolder() {}
178
eseckler7233c1a72017-01-25 15:07:54179 base::RunLoop run_loop_;
[email protected]c051d5a52014-01-08 23:54:51180 gfx::Image image_;
181 bool completed_;
182 };
183
jonross1ec7d992018-08-31 03:55:54184 std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_;
Mohsen Izadib3710182019-04-30 04:57:35185 std::unique_ptr<ui::TestContextFactories> context_factories_;
danakj25c52c32016-04-12 21:51:08186 std::unique_ptr<aura::test::AuraTestHelper> helper_;
187 std::unique_ptr<aura::Window> test_window_;
188 std::unique_ptr<TestPaintingWindowDelegate> delegate_;
[email protected]f95805472013-05-25 04:31:19189 std::vector<unsigned char> png_representation_;
190
191 DISALLOW_COPY_AND_ASSIGN(SnapshotAuraTest);
192};
193
Nico Webere29a31ae2018-06-13 23:00:36194#if defined(OS_WIN) && !defined(NDEBUG)
195// https://crbug.com/852512
196#define MAYBE_FullScreenWindow DISABLED_FullScreenWindow
197#else
198#define MAYBE_FullScreenWindow FullScreenWindow
199#endif
200TEST_F(SnapshotAuraTest, MAYBE_FullScreenWindow) {
Nico Webera79a1192018-06-13 14:13:28201#if defined(OS_WIN)
202 // TODO(https://crbug.com/850556): Make work on Win10.
203 base::win::Version version = base::win::GetVersion();
Bruce Dawsonaed9bea2019-04-20 02:30:09204 if (version >= base::win::Version::WIN10)
Nico Webera79a1192018-06-13 14:13:28205 return;
206#endif
[email protected]f95805472013-05-25 04:31:19207 SetupTestWindow(root_window()->bounds());
208 WaitForDraw();
209
210 gfx::Image snapshot = GrabSnapshotForTestWindow();
211 EXPECT_EQ(test_window()->bounds().size().ToString(),
212 snapshot.Size().ToString());
213 EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
214}
215
[email protected]43ea25e32014-01-16 22:36:15216TEST_F(SnapshotAuraTest, PartialBounds) {
Nico Webera79a1192018-06-13 14:13:28217#if defined(OS_WIN)
218 // TODO(https://crbug.com/850556): Make work on Win10.
219 base::win::Version version = base::win::GetVersion();
Bruce Dawsonaed9bea2019-04-20 02:30:09220 if (version >= base::win::Version::WIN10)
Nico Webera79a1192018-06-13 14:13:28221 return;
222#endif
[email protected]f95805472013-05-25 04:31:19223 gfx::Rect test_bounds(100, 100, 300, 200);
224 SetupTestWindow(test_bounds);
225 WaitForDraw();
226
227 gfx::Image snapshot = GrabSnapshotForTestWindow();
[email protected]7cfd3d22014-01-24 07:26:15228 EXPECT_EQ(test_bounds.size().ToString(), snapshot.Size().ToString());
[email protected]f95805472013-05-25 04:31:19229 EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
230}
231
[email protected]43ea25e32014-01-16 22:36:15232TEST_F(SnapshotAuraTest, Rotated) {
Nico Webera79a1192018-06-13 14:13:28233#if defined(OS_WIN)
234 // TODO(https://crbug.com/850556): Make work on Win10.
235 base::win::Version version = base::win::GetVersion();
Bruce Dawsonaed9bea2019-04-20 02:30:09236 if (version >= base::win::Version::WIN10)
Nico Webera79a1192018-06-13 14:13:28237 return;
238#endif
oshima5245e492016-04-26 16:47:55239 test_screen()->SetDisplayRotation(display::Display::ROTATE_90);
[email protected]f95805472013-05-25 04:31:19240
241 gfx::Rect test_bounds(100, 100, 300, 200);
242 SetupTestWindow(test_bounds);
243 WaitForDraw();
244
245 gfx::Image snapshot = GrabSnapshotForTestWindow();
[email protected]7cfd3d22014-01-24 07:26:15246 EXPECT_EQ(test_bounds.size().ToString(), snapshot.Size().ToString());
[email protected]f95805472013-05-25 04:31:19247 EXPECT_EQ(0u, GetFailedPixelsCount(snapshot));
248}
249
[email protected]43ea25e32014-01-16 22:36:15250TEST_F(SnapshotAuraTest, UIScale) {
Nico Webera79a1192018-06-13 14:13:28251#if defined(OS_WIN)
252 // TODO(https://crbug.com/850556): Make work on Win10.
253 base::win::Version version = base::win::GetVersion();
Bruce Dawsonaed9bea2019-04-20 02:30:09254 if (version >= base::win::Version::WIN10)
Nico Webera79a1192018-06-13 14:13:28255 return;
256#endif
eseckler7233c1a72017-01-25 15:07:54257 const float kUIScale = 0.5f;
[email protected]f95805472013-05-25 04:31:19258 test_screen()->SetUIScale(kUIScale);
259
260 gfx::Rect test_bounds(100, 100, 300, 200);
261 SetupTestWindow(test_bounds);
262 WaitForDraw();
263
264 // Snapshot always captures the physical pixels.
265 gfx::SizeF snapshot_size(test_bounds.size());
eseckler7233c1a72017-01-25 15:07:54266 snapshot_size.Scale(1 / kUIScale);
[email protected]f95805472013-05-25 04:31:19267
268 gfx::Image snapshot = GrabSnapshotForTestWindow();
269 EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(),
270 snapshot.Size().ToString());
eseckler7233c1a72017-01-25 15:07:54271 EXPECT_EQ(0u, GetFailedPixelsCountWithScaleFactor(snapshot, 1 / kUIScale));
[email protected]f95805472013-05-25 04:31:19272}
273
[email protected]43ea25e32014-01-16 22:36:15274TEST_F(SnapshotAuraTest, DeviceScaleFactor) {
Nico Webera79a1192018-06-13 14:13:28275#if defined(OS_WIN)
276 // TODO(https://crbug.com/850556): Make work on Win10.
277 base::win::Version version = base::win::GetVersion();
Bruce Dawsonaed9bea2019-04-20 02:30:09278 if (version >= base::win::Version::WIN10)
Nico Webera79a1192018-06-13 14:13:28279 return;
280#endif
[email protected]f95805472013-05-25 04:31:19281 test_screen()->SetDeviceScaleFactor(2.0f);
282
283 gfx::Rect test_bounds(100, 100, 150, 100);
284 SetupTestWindow(test_bounds);
285 WaitForDraw();
286
287 // Snapshot always captures the physical pixels.
288 gfx::SizeF snapshot_size(test_bounds.size());
289 snapshot_size.Scale(2.0f);
290
291 gfx::Image snapshot = GrabSnapshotForTestWindow();
292 EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(),
293 snapshot.Size().ToString());
[email protected]7cfd3d22014-01-24 07:26:15294 EXPECT_EQ(0u, GetFailedPixelsCountWithScaleFactor(snapshot, 2));
[email protected]f95805472013-05-25 04:31:19295}
296
[email protected]43ea25e32014-01-16 22:36:15297TEST_F(SnapshotAuraTest, RotateAndUIScale) {
Nico Webera79a1192018-06-13 14:13:28298#if defined(OS_WIN)
299 // TODO(https://crbug.com/850556): Make work on Win10.
300 base::win::Version version = base::win::GetVersion();
Bruce Dawsonaed9bea2019-04-20 02:30:09301 if (version >= base::win::Version::WIN10)
Nico Webera79a1192018-06-13 14:13:28302 return;
303#endif
eseckler7233c1a72017-01-25 15:07:54304 const float kUIScale = 0.5f;
[email protected]f95805472013-05-25 04:31:19305 test_screen()->SetUIScale(kUIScale);
oshima5245e492016-04-26 16:47:55306 test_screen()->SetDisplayRotation(display::Display::ROTATE_90);
[email protected]f95805472013-05-25 04:31:19307
308 gfx::Rect test_bounds(100, 100, 300, 200);
309 SetupTestWindow(test_bounds);
310 WaitForDraw();
311
312 // Snapshot always captures the physical pixels.
313 gfx::SizeF snapshot_size(test_bounds.size());
eseckler7233c1a72017-01-25 15:07:54314 snapshot_size.Scale(1 / kUIScale);
[email protected]f95805472013-05-25 04:31:19315
316 gfx::Image snapshot = GrabSnapshotForTestWindow();
317 EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(),
318 snapshot.Size().ToString());
eseckler7233c1a72017-01-25 15:07:54319 EXPECT_EQ(0u, GetFailedPixelsCountWithScaleFactor(snapshot, 1 / kUIScale));
[email protected]f95805472013-05-25 04:31:19320}
321
[email protected]43ea25e32014-01-16 22:36:15322TEST_F(SnapshotAuraTest, RotateAndUIScaleAndScaleFactor) {
Nico Webera79a1192018-06-13 14:13:28323#if defined(OS_WIN)
324 // TODO(https://crbug.com/850556): Make work on Win10.
325 base::win::Version version = base::win::GetVersion();
Bruce Dawsonaed9bea2019-04-20 02:30:09326 if (version >= base::win::Version::WIN10)
Nico Webera79a1192018-06-13 14:13:28327 return;
328#endif
[email protected]f95805472013-05-25 04:31:19329 test_screen()->SetDeviceScaleFactor(2.0f);
eseckler7233c1a72017-01-25 15:07:54330 const float kUIScale = 0.5f;
[email protected]f95805472013-05-25 04:31:19331 test_screen()->SetUIScale(kUIScale);
oshima5245e492016-04-26 16:47:55332 test_screen()->SetDisplayRotation(display::Display::ROTATE_90);
[email protected]f95805472013-05-25 04:31:19333
334 gfx::Rect test_bounds(20, 30, 150, 100);
335 SetupTestWindow(test_bounds);
336 WaitForDraw();
337
338 // Snapshot always captures the physical pixels.
339 gfx::SizeF snapshot_size(test_bounds.size());
eseckler7233c1a72017-01-25 15:07:54340 snapshot_size.Scale(2.0f / kUIScale);
[email protected]f95805472013-05-25 04:31:19341
342 gfx::Image snapshot = GrabSnapshotForTestWindow();
343 EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(),
344 snapshot.Size().ToString());
eseckler7233c1a72017-01-25 15:07:54345 EXPECT_EQ(0u, GetFailedPixelsCountWithScaleFactor(snapshot, 2 / kUIScale));
[email protected]f95805472013-05-25 04:31:19346}
347
348} // namespace ui