blob: 533019fea1120118c30bf2b6a328b6ec64d46e87 [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// 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 "base/command_line.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01006#include "base/message_loop/message_loop_proxy.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00007#include "base/path_service.h"
8#include "base/run_loop.h"
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +01009#include "content/browser/gpu/compositor_util.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010#include "content/browser/gpu/gpu_data_manager_impl.h"
Ben Murdoch558790d2013-07-30 15:19:42 +010011#include "content/browser/renderer_host/dip_util.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000012#include "content/browser/renderer_host/render_widget_host_impl.h"
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010013#include "content/browser/renderer_host/render_widget_host_view_base.h"
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010014#include "content/public/browser/gpu_data_manager.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000015#include "content/public/browser/render_view_host.h"
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010016#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000017#include "content/public/browser/web_contents.h"
18#include "content/public/common/content_paths.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010019#include "content/public/common/content_switches.h"
Ben Murdoch2385ea32013-08-06 11:01:04 +010020#include "content/public/common/url_constants.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010021#include "content/public/test/browser_test_utils.h"
Ben Murdocheffb81e2014-03-31 11:51:25 +010022#include "content/public/test/content_browser_test.h"
23#include "content/public/test/content_browser_test_utils.h"
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +010024#include "content/shell/browser/shell.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000025#include "media/base/video_frame.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010026#include "media/filters/skcanvas_video_renderer.h"
Ben Murdochc5cede92014-04-10 11:22:14 +010027#include "net/base/filename_util.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010028#include "third_party/skia/include/core/SkBitmap.h"
29#include "third_party/skia/include/core/SkCanvas.h"
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010030#include "ui/base/layout.h"
Ben Murdoch558790d2013-07-30 15:19:42 +010031#include "ui/base/ui_base_switches.h"
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010032#include "ui/gfx/geometry/size_conversions.h"
Torne (Richard Coles)58537e22013-09-12 12:10:22 +010033#include "ui/gfx/switches.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010034#include "ui/gl/gl_switches.h"
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010035
Ben Murdoch558790d2013-07-30 15:19:42 +010036#if defined(OS_WIN)
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +010037#include "base/win/windows_version.h"
38#include "ui/gfx/win/dpi.h"
Ben Murdoch558790d2013-07-30 15:19:42 +010039#endif
40
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000041namespace content {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010042namespace {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000043
Ben Murdoch558790d2013-07-30 15:19:42 +010044// Convenience macro: Short-circuit a pass for the tests where platform support
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010045// for forced-compositing mode (or disabled-compositing mode) is lacking.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010046#define SET_UP_SURFACE_OR_PASS_TEST(wait_message) \
47 if (!SetUpSourceSurface(wait_message)) { \
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010048 LOG(WARNING) \
49 << ("Blindly passing this test: This platform does not support " \
50 "forced compositing (or forced-disabled compositing) mode."); \
51 return; \
52 }
53
54// Common base class for browser tests. This is subclassed twice: Once to test
55// the browser in forced-compositing mode, and once to test with compositing
56// mode disabled.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000057class RenderWidgetHostViewBrowserTest : public ContentBrowserTest {
58 public:
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010059 RenderWidgetHostViewBrowserTest()
60 : frame_size_(400, 300),
61 callback_invoke_count_(0),
62 frames_captured_(0) {}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000063
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000064 virtual void SetUpOnMainThread() OVERRIDE {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000065 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir_));
66 }
67
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010068 // Attempts to set up the source surface. Returns false if unsupported on the
69 // current platform.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010070 virtual bool SetUpSourceSurface(const char* wait_message) = 0;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010071
72 int callback_invoke_count() const {
73 return callback_invoke_count_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000074 }
75
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010076 int frames_captured() const {
77 return frames_captured_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000078 }
79
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010080 const gfx::Size& frame_size() const {
81 return frame_size_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000082 }
83
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010084 const base::FilePath& test_dir() const {
85 return test_dir_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000086 }
87
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010088 RenderViewHost* GetRenderViewHost() const {
89 RenderViewHost* const rvh = shell()->web_contents()->GetRenderViewHost();
90 CHECK(rvh);
91 return rvh;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000092 }
93
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010094 RenderWidgetHostImpl* GetRenderWidgetHost() const {
95 RenderWidgetHostImpl* const rwh = RenderWidgetHostImpl::From(
96 shell()->web_contents()->GetRenderWidgetHostView()->
97 GetRenderWidgetHost());
98 CHECK(rwh);
99 return rwh;
100 }
101
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100102 RenderWidgetHostViewBase* GetRenderWidgetHostView() const {
103 return static_cast<RenderWidgetHostViewBase*>(
104 GetRenderViewHost()->GetView());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100105 }
106
107 // Callback when using CopyFromBackingStore() API.
108 void FinishCopyFromBackingStore(const base::Closure& quit_closure,
109 bool frame_captured,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000110 const SkBitmap& bitmap) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100111 ++callback_invoke_count_;
112 if (frame_captured) {
113 ++frames_captured_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000114 EXPECT_FALSE(bitmap.empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100115 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000116 if (!quit_closure.is_null())
117 quit_closure.Run();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100118 }
119
120 // Callback when using CopyFromCompositingSurfaceToVideoFrame() API.
121 void FinishCopyFromCompositingSurface(const base::Closure& quit_closure,
122 bool frame_captured) {
123 ++callback_invoke_count_;
124 if (frame_captured)
125 ++frames_captured_;
126 if (!quit_closure.is_null())
127 quit_closure.Run();
128 }
129
130 // Callback when using frame subscriber API.
131 void FrameDelivered(const scoped_refptr<base::MessageLoopProxy>& loop,
132 base::Closure quit_closure,
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000133 base::TimeTicks timestamp,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100134 bool frame_captured) {
135 ++callback_invoke_count_;
136 if (frame_captured)
137 ++frames_captured_;
138 if (!quit_closure.is_null())
139 loop->PostTask(FROM_HERE, quit_closure);
140 }
141
142 // Copy one frame using the CopyFromBackingStore API.
143 void RunBasicCopyFromBackingStoreTest() {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100144 SET_UP_SURFACE_OR_PASS_TEST(NULL);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100145
146 // Repeatedly call CopyFromBackingStore() since, on some platforms (e.g.,
147 // Windows), the operation will fail until the first "present" has been
148 // made.
149 int count_attempts = 0;
150 while (true) {
151 ++count_attempts;
152 base::RunLoop run_loop;
153 GetRenderViewHost()->CopyFromBackingStore(
154 gfx::Rect(),
155 frame_size(),
156 base::Bind(
157 &RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
158 base::Unretained(this),
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000159 run_loop.QuitClosure()),
Ben Murdoch116680a2014-07-20 18:25:52 -0700160 kN32_SkColorType);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100161 run_loop.Run();
162
163 if (frames_captured())
164 break;
165 else
166 GiveItSomeTime();
167 }
168
169 EXPECT_EQ(count_attempts, callback_invoke_count());
170 EXPECT_EQ(1, frames_captured());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000171 }
172
173 protected:
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100174 // Waits until the source is available for copying.
175 void WaitForCopySourceReady() {
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100176 while (!GetRenderWidgetHostView()->IsSurfaceAvailableForCopy())
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100177 GiveItSomeTime();
178 }
179
180 // Run the current message loop for a short time without unwinding the current
181 // call stack.
182 static void GiveItSomeTime() {
183 base::RunLoop run_loop;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100184 base::MessageLoop::current()->PostDelayedTask(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100185 FROM_HERE,
186 run_loop.QuitClosure(),
187 base::TimeDelta::FromMilliseconds(10));
188 run_loop.Run();
189 }
190
191 private:
192 const gfx::Size frame_size_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000193 base::FilePath test_dir_;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100194 int callback_invoke_count_;
195 int frames_captured_;
196};
197
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000198enum CompositingMode {
199 GL_COMPOSITING,
200 SOFTWARE_COMPOSITING,
201};
202
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100203class CompositingRenderWidgetHostViewBrowserTest
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000204 : public RenderWidgetHostViewBrowserTest,
205 public testing::WithParamInterface<CompositingMode> {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100206 public:
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000207 explicit CompositingRenderWidgetHostViewBrowserTest()
208 : compositing_mode_(GetParam()) {}
209
Ben Murdochc2db58b2013-08-14 11:51:42 +0100210 virtual void SetUp() OVERRIDE {
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000211 if (compositing_mode_ == SOFTWARE_COMPOSITING)
212 UseSoftwareCompositing();
Ben Murdochc2db58b2013-08-14 11:51:42 +0100213 RenderWidgetHostViewBrowserTest::SetUp();
214 }
215
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100216 virtual GURL TestUrl() {
217 return net::FilePathToFileURL(
218 test_dir().AppendASCII("rwhv_compositing_animation.html"));
219 }
220
221 virtual bool SetUpSourceSurface(const char* wait_message) OVERRIDE {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100222 content::DOMMessageQueue message_queue;
223 NavigateToURL(shell(), TestUrl());
224 if (wait_message != NULL) {
225 std::string result(wait_message);
226 if (!message_queue.WaitForMessage(&result)) {
227 EXPECT_TRUE(false) << "WaitForMessage " << result << " failed.";
228 return false;
229 }
230 }
231
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100232 // A frame might not be available yet. So, wait for it.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100233 WaitForCopySourceReady();
234 return true;
235 }
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000236
237 private:
238 const CompositingMode compositing_mode_;
239
240 DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewBrowserTest);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100241};
242
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000243class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
244 public:
245 FakeFrameSubscriber(
246 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback)
247 : callback_(callback) {
248 }
249
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100250 virtual bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
251 base::TimeTicks present_time,
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000252 scoped_refptr<media::VideoFrame>* storage,
253 DeliverFrameCallback* callback) OVERRIDE {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100254 // Only allow one frame capture to be made. Otherwise, the compositor could
255 // start multiple captures, unbounded, and eventually its own limiter logic
256 // will begin invoking |callback| with a |false| result. This flakes out
257 // the unit tests, since they receive a "failed" callback before the later
258 // "success" callbacks.
259 if (callback_.is_null())
260 return false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000261 *storage = media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
262 *callback = callback_;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100263 callback_.Reset();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000264 return true;
265 }
266
267 private:
268 DeliverFrameCallback callback_;
269};
270
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100271// Disable tests for Android and IOS as these platforms have incomplete
272// implementation.
273#if !defined(OS_ANDROID) && !defined(OS_IOS)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000274
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100275// The CopyFromBackingStore() API should work on all platforms when compositing
276// is enabled.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000277IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100278 CopyFromBackingStore) {
279 RunBasicCopyFromBackingStoreTest();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000280}
281
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100282// Tests that the callback passed to CopyFromBackingStore is always called,
283// even when the RenderWidgetHost is deleting in the middle of an async copy.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000284IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100285 CopyFromBackingStore_CallbackDespiteDelete) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100286 SET_UP_SURFACE_OR_PASS_TEST(NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000287
288 base::RunLoop run_loop;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100289 GetRenderViewHost()->CopyFromBackingStore(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000290 gfx::Rect(),
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100291 frame_size(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000292 base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000293 base::Unretained(this),
294 run_loop.QuitClosure()),
Ben Murdoch116680a2014-07-20 18:25:52 -0700295 kN32_SkColorType);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100296 // Delete the surface before the callback is run.
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100297 GetRenderWidgetHostView()->AcceleratedSurfaceRelease();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000298 run_loop.Run();
299
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100300 EXPECT_EQ(1, callback_invoke_count());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000301}
302
303// Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is
304// always called, even when the RenderWidgetHost is deleting in the middle of
305// an async copy.
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100306//
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000307// Test is flaky on Win. http://crbug.com/276783
308#if defined(OS_WIN) || (defined(OS_CHROMEOS) && !defined(NDEBUG))
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100309#define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
310 DISABLED_CopyFromCompositingSurface_CallbackDespiteDelete
311#else
312#define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
313 CopyFromCompositingSurface_CallbackDespiteDelete
314#endif
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000315IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100316 MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100317 SET_UP_SURFACE_OR_PASS_TEST(NULL);
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100318 RenderWidgetHostViewBase* const view = GetRenderWidgetHostView();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100319 if (!view->CanCopyToVideoFrame()) {
320 LOG(WARNING) <<
321 ("Blindly passing this test: CopyFromCompositingSurfaceToVideoFrame() "
322 "not supported on this platform.");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000323 return;
324 }
Ben Murdochc2db58b2013-08-14 11:51:42 +0100325
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000326 base::RunLoop run_loop;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000327 scoped_refptr<media::VideoFrame> dest =
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100328 media::VideoFrame::CreateBlackFrame(frame_size());
329 view->CopyFromCompositingSurfaceToVideoFrame(
330 gfx::Rect(view->GetViewBounds().size()), dest, base::Bind(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000331 &RenderWidgetHostViewBrowserTest::FinishCopyFromCompositingSurface,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100332 base::Unretained(this), run_loop.QuitClosure()));
333 // Delete the surface before the callback is run.
334 view->AcceleratedSurfaceRelease();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000335 run_loop.Run();
336
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100337 EXPECT_EQ(1, callback_invoke_count());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000338}
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100339
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100340// Test basic frame subscription functionality. We subscribe, and then run
341// until at least one DeliverFrameCallback has been invoked.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000342IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100343 FrameSubscriberTest) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100344 SET_UP_SURFACE_OR_PASS_TEST(NULL);
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100345 RenderWidgetHostViewBase* const view = GetRenderWidgetHostView();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100346 if (!view->CanSubscribeFrame()) {
347 LOG(WARNING) << ("Blindly passing this test: Frame subscription not "
348 "supported on this platform.");
349 return;
350 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000351
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000352 base::RunLoop run_loop;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000353 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100354 new FakeFrameSubscriber(
355 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
356 base::Unretained(this),
357 base::MessageLoopProxy::current(),
358 run_loop.QuitClosure())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000359 view->BeginFrameSubscription(subscriber.Pass());
360 run_loop.Run();
361 view->EndFrameSubscription();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100362
363 EXPECT_LE(1, callback_invoke_count());
364 EXPECT_LE(1, frames_captured());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000365}
366
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000367// Test that we can copy twice from an accelerated composited page.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000368IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest, CopyTwice) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100369 SET_UP_SURFACE_OR_PASS_TEST(NULL);
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100370 RenderWidgetHostViewBase* const view = GetRenderWidgetHostView();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100371 if (!view->CanCopyToVideoFrame()) {
372 LOG(WARNING) << ("Blindly passing this test: "
373 "CopyFromCompositingSurfaceToVideoFrame() not supported "
374 "on this platform.");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000375 return;
376 }
377
378 base::RunLoop run_loop;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100379 scoped_refptr<media::VideoFrame> first_output =
380 media::VideoFrame::CreateBlackFrame(frame_size());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100381 ASSERT_TRUE(first_output.get());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100382 scoped_refptr<media::VideoFrame> second_output =
383 media::VideoFrame::CreateBlackFrame(frame_size());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100384 ASSERT_TRUE(second_output.get());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100385 view->CopyFromCompositingSurfaceToVideoFrame(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100386 gfx::Rect(view->GetViewBounds().size()),
387 first_output,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100388 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
389 base::Unretained(this),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000390 base::MessageLoopProxy::current(),
391 base::Closure(),
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000392 base::TimeTicks::Now()));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100393 view->CopyFromCompositingSurfaceToVideoFrame(
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000394 gfx::Rect(view->GetViewBounds().size()),
395 second_output,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100396 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
397 base::Unretained(this),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000398 base::MessageLoopProxy::current(),
399 run_loop.QuitClosure(),
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000400 base::TimeTicks::Now()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000401 run_loop.Run();
402
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100403 EXPECT_EQ(2, callback_invoke_count());
404 EXPECT_EQ(2, frames_captured());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000405}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000406
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100407class CompositingRenderWidgetHostViewBrowserTestTabCapture
408 : public CompositingRenderWidgetHostViewBrowserTest {
409 public:
410 CompositingRenderWidgetHostViewBrowserTestTabCapture()
411 : expected_copy_from_compositing_surface_result_(false),
412 allowable_error_(0),
413 test_url_("data:text/html,<!doctype html>") {}
414
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000415 virtual void SetUp() OVERRIDE {
416 EnablePixelOutput();
417 CompositingRenderWidgetHostViewBrowserTest::SetUp();
418 }
419
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100420 void CopyFromCompositingSurfaceCallback(base::Closure quit_callback,
421 bool result,
422 const SkBitmap& bitmap) {
423 EXPECT_EQ(expected_copy_from_compositing_surface_result_, result);
424 if (!result) {
425 quit_callback.Run();
426 return;
427 }
428
429 const SkBitmap& expected_bitmap =
430 expected_copy_from_compositing_surface_bitmap_;
431 EXPECT_EQ(expected_bitmap.width(), bitmap.width());
432 EXPECT_EQ(expected_bitmap.height(), bitmap.height());
Ben Murdoch116680a2014-07-20 18:25:52 -0700433 EXPECT_EQ(expected_bitmap.colorType(), bitmap.colorType());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100434 SkAutoLockPixels expected_bitmap_lock(expected_bitmap);
435 SkAutoLockPixels bitmap_lock(bitmap);
436 int fails = 0;
437 for (int i = 0; i < bitmap.width() && fails < 10; ++i) {
438 for (int j = 0; j < bitmap.height() && fails < 10; ++j) {
439 if (!exclude_rect_.IsEmpty() && exclude_rect_.Contains(i, j))
440 continue;
441
442 SkColor expected_color = expected_bitmap.getColor(i, j);
443 SkColor color = bitmap.getColor(i, j);
444 int expected_alpha = SkColorGetA(expected_color);
445 int alpha = SkColorGetA(color);
446 int expected_red = SkColorGetR(expected_color);
447 int red = SkColorGetR(color);
448 int expected_green = SkColorGetG(expected_color);
449 int green = SkColorGetG(color);
450 int expected_blue = SkColorGetB(expected_color);
451 int blue = SkColorGetB(color);
452 EXPECT_NEAR(expected_alpha, alpha, allowable_error_)
453 << "expected_color: " << std::hex << expected_color
454 << " color: " << color
455 << " Failed at " << std::dec << i << ", " << j
456 << " Failure " << ++fails;
457 EXPECT_NEAR(expected_red, red, allowable_error_)
458 << "expected_color: " << std::hex << expected_color
459 << " color: " << color
460 << " Failed at " << std::dec << i << ", " << j
461 << " Failure " << ++fails;
462 EXPECT_NEAR(expected_green, green, allowable_error_)
463 << "expected_color: " << std::hex << expected_color
464 << " color: " << color
465 << " Failed at " << std::dec << i << ", " << j
466 << " Failure " << ++fails;
467 EXPECT_NEAR(expected_blue, blue, allowable_error_)
468 << "expected_color: " << std::hex << expected_color
469 << " color: " << color
470 << " Failed at " << std::dec << i << ", " << j
471 << " Failure " << ++fails;
472 }
473 }
474 EXPECT_LT(fails, 10);
475
476 quit_callback.Run();
477 }
478
479 void CopyFromCompositingSurfaceCallbackForVideo(
480 scoped_refptr<media::VideoFrame> video_frame,
481 base::Closure quit_callback,
482 bool result) {
483 EXPECT_EQ(expected_copy_from_compositing_surface_result_, result);
484 if (!result) {
485 quit_callback.Run();
486 return;
487 }
488
489 media::SkCanvasVideoRenderer video_renderer;
490
491 SkBitmap bitmap;
Ben Murdoch116680a2014-07-20 18:25:52 -0700492 bitmap.allocN32Pixels(video_frame->visible_rect().width(),
493 video_frame->visible_rect().height());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100494 bitmap.eraseColor(SK_ColorTRANSPARENT);
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000495 SkCanvas canvas(bitmap);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100496
497 video_renderer.Paint(video_frame.get(),
498 &canvas,
499 video_frame->visible_rect(),
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100500 0xff,
501 media::VIDEO_ROTATION_0);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100502
503 CopyFromCompositingSurfaceCallback(quit_callback,
504 result,
505 bitmap);
506 }
507
508 void SetExpectedCopyFromCompositingSurfaceResult(bool result,
509 const SkBitmap& bitmap) {
510 expected_copy_from_compositing_surface_result_ = result;
511 expected_copy_from_compositing_surface_bitmap_ = bitmap;
512 }
513
514 void SetAllowableError(int amount) { allowable_error_ = amount; }
515 void SetExcludeRect(gfx::Rect exclude) { exclude_rect_ = exclude; }
516
517 virtual GURL TestUrl() OVERRIDE {
518 return GURL(test_url_);
519 }
520
521 void SetTestUrl(std::string url) { test_url_ = url; }
522
Ben Murdoch558790d2013-07-30 15:19:42 +0100523 // Loads a page two boxes side-by-side, each half the width of
524 // |html_rect_size|, and with different background colors. The test then
525 // copies from |copy_rect| region of the page into a bitmap of size
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100526 // |output_size|, and examines the resulting bitmap/VideoFrame.
Ben Murdoch558790d2013-07-30 15:19:42 +0100527 // Note that |output_size| may not have the same size as |copy_rect| (e.g.
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100528 // when the output is scaled).
Ben Murdoch558790d2013-07-30 15:19:42 +0100529 void PerformTestWithLeftRightRects(const gfx::Size& html_rect_size,
530 const gfx::Rect& copy_rect,
531 const gfx::Size& output_size,
Ben Murdoch558790d2013-07-30 15:19:42 +0100532 bool video_frame) {
533 const gfx::Size box_size(html_rect_size.width() / 2,
534 html_rect_size.height());
535 SetTestUrl(base::StringPrintf(
536 "data:text/html,<!doctype html>"
537 "<div class='left'>"
538 " <div class='right'></div>"
539 "</div>"
540 "<style>"
541 "body { padding: 0; margin: 0; }"
542 ".left { position: absolute;"
543 " background: #0ff;"
544 " width: %dpx;"
545 " height: %dpx;"
546 "}"
547 ".right { position: absolute;"
548 " left: %dpx;"
549 " background: #ff0;"
550 " width: %dpx;"
551 " height: %dpx;"
552 "}"
553 "</style>"
554 "<script>"
555 " domAutomationController.setAutomationId(0);"
556 " domAutomationController.send(\"DONE\");"
557 "</script>",
558 box_size.width(),
559 box_size.height(),
560 box_size.width(),
561 box_size.width(),
562 box_size.height()));
563
564 SET_UP_SURFACE_OR_PASS_TEST("\"DONE\"");
565 if (!ShouldContinueAfterTestURLLoad())
566 return;
567
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100568 RenderWidgetHostViewBase* rwhvp = GetRenderWidgetHostView();
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000569 if (video_frame && !rwhvp->CanCopyToVideoFrame()) {
570 // This should only happen on Mac when using the software compositor.
571 // Otherwise, raise an error. This can be removed when Mac is moved to a
572 // browser compositor.
573 // http://crbug.com/314190
574#if defined(OS_MACOSX)
575 if (!content::GpuDataManager::GetInstance()->GpuAccessAllowed(NULL)) {
576 LOG(WARNING) << ("Blindly passing this test because copying to "
577 "video frames is not supported on this platform.");
578 return;
579 }
580#endif
581 NOTREACHED();
582 }
Ben Murdoch558790d2013-07-30 15:19:42 +0100583
584 // The page is loaded in the renderer, wait for a new frame to arrive.
585 uint32 frame = rwhvp->RendererFrameNumber();
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100586 while (!GetRenderWidgetHost()->ScheduleComposite())
587 GiveItSomeTime();
Ben Murdoch558790d2013-07-30 15:19:42 +0100588 while (rwhvp->RendererFrameNumber() == frame)
589 GiveItSomeTime();
590
591 SkBitmap expected_bitmap;
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100592 SetupLeftRightBitmap(output_size, &expected_bitmap);
Ben Murdoch558790d2013-07-30 15:19:42 +0100593 SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap);
594
595 base::RunLoop run_loop;
596 if (video_frame) {
597 // Allow pixel differences as long as we have the right idea.
598 SetAllowableError(0x10);
599 // Exclude the middle two columns which are blended between the two sides.
600 SetExcludeRect(
601 gfx::Rect(output_size.width() / 2 - 1, 0, 2, output_size.height()));
602
603 scoped_refptr<media::VideoFrame> video_frame =
604 media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100605 output_size,
606 gfx::Rect(output_size),
607 output_size,
Ben Murdoch558790d2013-07-30 15:19:42 +0100608 base::TimeDelta());
609
610 base::Callback<void(bool success)> callback =
611 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
612 CopyFromCompositingSurfaceCallbackForVideo,
613 base::Unretained(this),
614 video_frame,
615 run_loop.QuitClosure());
616 rwhvp->CopyFromCompositingSurfaceToVideoFrame(copy_rect,
617 video_frame,
618 callback);
619 } else {
Ben Murdoch116680a2014-07-20 18:25:52 -0700620 if (IsDelegatedRendererEnabled()) {
621 if (!content::GpuDataManager::GetInstance()
622 ->CanUseGpuBrowserCompositor()) {
623 // Skia rendering can cause color differences, particularly in the
624 // middle two columns.
625 SetAllowableError(2);
626 SetExcludeRect(gfx::Rect(
627 output_size.width() / 2 - 1, 0, 2, output_size.height()));
628 }
Torne (Richard Coles)8bcbed82013-10-22 16:41:35 +0100629 }
Torne (Richard Coles)8bcbed82013-10-22 16:41:35 +0100630
Ben Murdoch558790d2013-07-30 15:19:42 +0100631 base::Callback<void(bool, const SkBitmap&)> callback =
632 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
633 CopyFromCompositingSurfaceCallback,
634 base::Unretained(this),
635 run_loop.QuitClosure());
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000636 rwhvp->CopyFromCompositingSurface(copy_rect,
637 output_size,
638 callback,
Ben Murdoch116680a2014-07-20 18:25:52 -0700639 kN32_SkColorType);
Ben Murdoch558790d2013-07-30 15:19:42 +0100640 }
641 run_loop.Run();
642 }
643
644 // Sets up |bitmap| to have size |copy_size|. It floods the left half with
645 // #0ff and the right half with #ff0.
646 void SetupLeftRightBitmap(const gfx::Size& copy_size, SkBitmap* bitmap) {
Ben Murdoch116680a2014-07-20 18:25:52 -0700647 bitmap->allocN32Pixels(copy_size.width(), copy_size.height());
Ben Murdoch558790d2013-07-30 15:19:42 +0100648 // Left half is #0ff.
649 bitmap->eraseARGB(255, 0, 255, 255);
650 // Right half is #ff0.
651 {
652 SkAutoLockPixels lock(*bitmap);
653 for (int i = 0; i < copy_size.width() / 2; ++i) {
654 for (int j = 0; j < copy_size.height(); ++j) {
655 *(bitmap->getAddr32(copy_size.width() / 2 + i, j)) =
656 SkColorSetARGB(255, 255, 255, 0);
657 }
658 }
659 }
660 }
661
662 protected:
663 virtual bool ShouldContinueAfterTestURLLoad() {
664 return true;
665 }
666
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100667 private:
668 bool expected_copy_from_compositing_surface_result_;
669 SkBitmap expected_copy_from_compositing_surface_bitmap_;
670 int allowable_error_;
671 gfx::Rect exclude_rect_;
672 std::string test_url_;
673};
674
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000675IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100676 CopyFromCompositingSurface_Origin_Unscaled) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100677 gfx::Rect copy_rect(400, 300);
678 gfx::Size output_size = copy_rect.size();
Ben Murdoch558790d2013-07-30 15:19:42 +0100679 gfx::Size html_rect_size(400, 300);
680 bool video_frame = false;
681 PerformTestWithLeftRightRects(html_rect_size,
682 copy_rect,
683 output_size,
Ben Murdoch558790d2013-07-30 15:19:42 +0100684 video_frame);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100685}
686
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000687IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100688 CopyFromCompositingSurface_Origin_Scaled) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100689 gfx::Rect copy_rect(400, 300);
690 gfx::Size output_size(200, 100);
Ben Murdoch558790d2013-07-30 15:19:42 +0100691 gfx::Size html_rect_size(400, 300);
692 bool video_frame = false;
693 PerformTestWithLeftRightRects(html_rect_size,
694 copy_rect,
695 output_size,
Ben Murdoch558790d2013-07-30 15:19:42 +0100696 video_frame);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100697}
698
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000699IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100700 CopyFromCompositingSurface_Cropped_Unscaled) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100701 // Grab 60x60 pixels from the center of the tab contents.
Ben Murdoch558790d2013-07-30 15:19:42 +0100702 gfx::Rect copy_rect(400, 300);
703 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
704 gfx::Size(60, 60));
705 gfx::Size output_size = copy_rect.size();
Ben Murdoch558790d2013-07-30 15:19:42 +0100706 gfx::Size html_rect_size(400, 300);
707 bool video_frame = false;
708 PerformTestWithLeftRightRects(html_rect_size,
709 copy_rect,
710 output_size,
Ben Murdoch558790d2013-07-30 15:19:42 +0100711 video_frame);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100712}
713
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000714IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100715 CopyFromCompositingSurface_Cropped_Scaled) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100716 // Grab 60x60 pixels from the center of the tab contents.
Ben Murdoch558790d2013-07-30 15:19:42 +0100717 gfx::Rect copy_rect(400, 300);
718 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
719 gfx::Size(60, 60));
720 gfx::Size output_size(20, 10);
Ben Murdoch558790d2013-07-30 15:19:42 +0100721 gfx::Size html_rect_size(400, 300);
722 bool video_frame = false;
723 PerformTestWithLeftRightRects(html_rect_size,
724 copy_rect,
725 output_size,
Ben Murdoch558790d2013-07-30 15:19:42 +0100726 video_frame);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100727}
728
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000729IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100730 CopyFromCompositingSurface_ForVideoFrame) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100731 // Grab 90x60 pixels from the center of the tab contents.
Ben Murdoch558790d2013-07-30 15:19:42 +0100732 gfx::Rect copy_rect(400, 300);
733 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(45, 30),
734 gfx::Size(90, 60));
735 gfx::Size output_size = copy_rect.size();
Ben Murdoch558790d2013-07-30 15:19:42 +0100736 gfx::Size html_rect_size(400, 300);
737 bool video_frame = true;
738 PerformTestWithLeftRightRects(html_rect_size,
739 copy_rect,
740 output_size,
Ben Murdoch558790d2013-07-30 15:19:42 +0100741 video_frame);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100742}
743
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000744IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100745 CopyFromCompositingSurface_ForVideoFrame_Scaled) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100746 // Grab 90x60 pixels from the center of the tab contents.
Ben Murdoch558790d2013-07-30 15:19:42 +0100747 gfx::Rect copy_rect(400, 300);
748 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(45, 30),
749 gfx::Size(90, 60));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100750 // Scale to 30 x 20 (preserve aspect ratio).
Ben Murdoch558790d2013-07-30 15:19:42 +0100751 gfx::Size output_size(30, 20);
Ben Murdoch558790d2013-07-30 15:19:42 +0100752 gfx::Size html_rect_size(400, 300);
753 bool video_frame = true;
754 PerformTestWithLeftRightRects(html_rect_size,
755 copy_rect,
756 output_size,
Ben Murdoch558790d2013-07-30 15:19:42 +0100757 video_frame);
758}
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100759
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100760class CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
Ben Murdoch558790d2013-07-30 15:19:42 +0100761 : public CompositingRenderWidgetHostViewBrowserTestTabCapture {
762 public:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100763 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI() {}
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100764
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100765 protected:
766 virtual void SetUpCommandLine(base::CommandLine* cmd) OVERRIDE {
767 CompositingRenderWidgetHostViewBrowserTestTabCapture::SetUpCommandLine(cmd);
Ben Murdoch558790d2013-07-30 15:19:42 +0100768 cmd->AppendSwitchASCII(switches::kForceDeviceScaleFactor,
769 base::StringPrintf("%f", scale()));
Ben Murdoch558790d2013-07-30 15:19:42 +0100770 }
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100771
Ben Murdoch558790d2013-07-30 15:19:42 +0100772 virtual bool ShouldContinueAfterTestURLLoad() OVERRIDE {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100773 // Short-circuit a pass for platforms where setting up high-DPI fails.
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100774 const float actual_scale_factor =
775 GetScaleFactorForView(GetRenderWidgetHostView());
776 if (actual_scale_factor != scale()) {
777 LOG(WARNING) << "Blindly passing this test; unable to force device scale "
778 << "factor: seems to be " << actual_scale_factor
779 << " but expected " << scale();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100780 return false;
781 }
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100782 VLOG(1) << ("Successfully forced device scale factor. Moving forward with "
783 "this test! :-)");
Ben Murdoch558790d2013-07-30 15:19:42 +0100784 return true;
785 }
786
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100787 static float scale() { return 2.0f; }
Ben Murdoch558790d2013-07-30 15:19:42 +0100788
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100789 private:
790 DISALLOW_COPY_AND_ASSIGN(
791 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI);
Ben Murdoch558790d2013-07-30 15:19:42 +0100792};
793
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100794// ImageSkia (related to ResourceBundle) implementation crashes the process on
795// Windows when this content_browsertest forces a device scale factor.
796// http://crbug.com/399349
797#if defined(OS_WIN)
798#define MAYBE_CopyToBitmap_EntireRegion DISABLED_CopyToBitmap_EntireRegion
799#define MAYBE_CopyToBitmap_CenterRegion DISABLED_CopyToBitmap_CenterRegion
800#define MAYBE_CopyToBitmap_ScaledResult DISABLED_CopyToBitmap_ScaledResult
801#define MAYBE_CopyToVideoFrame_EntireRegion \
802 DISABLED_CopyToVideoFrame_EntireRegion
803#define MAYBE_CopyToVideoFrame_CenterRegion \
804 DISABLED_CopyToVideoFrame_CenterRegion
805#define MAYBE_CopyToVideoFrame_ScaledResult \
806 DISABLED_CopyToVideoFrame_ScaledResult
807#else
808#define MAYBE_CopyToBitmap_EntireRegion CopyToBitmap_EntireRegion
809#define MAYBE_CopyToBitmap_CenterRegion CopyToBitmap_CenterRegion
810#define MAYBE_CopyToBitmap_ScaledResult CopyToBitmap_ScaledResult
811#define MAYBE_CopyToVideoFrame_EntireRegion CopyToVideoFrame_EntireRegion
812#define MAYBE_CopyToVideoFrame_CenterRegion CopyToVideoFrame_CenterRegion
813#define MAYBE_CopyToVideoFrame_ScaledResult CopyToVideoFrame_ScaledResult
814#endif
815
816IN_PROC_BROWSER_TEST_P(
817 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
818 MAYBE_CopyToBitmap_EntireRegion) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100819 gfx::Size html_rect_size(200, 150);
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100820 gfx::Rect copy_rect(200, 150);
821 // Scale the output size so that, internally, scaling is not occurring.
822 gfx::Size output_size =
823 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
Ben Murdoch558790d2013-07-30 15:19:42 +0100824 bool video_frame = false;
825 PerformTestWithLeftRightRects(html_rect_size,
826 copy_rect,
Ben Murdochd3868032013-07-31 10:55:33 +0100827 output_size,
Ben Murdochd3868032013-07-31 10:55:33 +0100828 video_frame);
829}
830
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100831IN_PROC_BROWSER_TEST_P(
832 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
833 MAYBE_CopyToBitmap_CenterRegion) {
Ben Murdochd3868032013-07-31 10:55:33 +0100834 gfx::Size html_rect_size(200, 150);
835 // Grab 90x60 pixels from the center of the tab contents.
836 gfx::Rect copy_rect =
837 gfx::Rect(gfx::Rect(html_rect_size).CenterPoint() - gfx::Vector2d(45, 30),
838 gfx::Size(90, 60));
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100839 // Scale the output size so that, internally, scaling is not occurring.
840 gfx::Size output_size =
841 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
842 bool video_frame = false;
843 PerformTestWithLeftRightRects(html_rect_size,
844 copy_rect,
845 output_size,
846 video_frame);
847}
848
849IN_PROC_BROWSER_TEST_P(
850 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
851 MAYBE_CopyToBitmap_ScaledResult) {
852 gfx::Size html_rect_size(200, 100);
853 gfx::Rect copy_rect(200, 100);
854 // Output is being down-scaled since output_size is in phyiscal pixels.
855 gfx::Size output_size(200, 100);
856 bool video_frame = false;
857 PerformTestWithLeftRightRects(html_rect_size,
858 copy_rect,
859 output_size,
860 video_frame);
861}
862
863IN_PROC_BROWSER_TEST_P(
864 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
865 MAYBE_CopyToVideoFrame_EntireRegion) {
866 gfx::Size html_rect_size(200, 150);
867 gfx::Rect copy_rect(200, 150);
868 // Scale the output size so that, internally, scaling is not occurring.
869 gfx::Size output_size =
870 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
Ben Murdochd3868032013-07-31 10:55:33 +0100871 bool video_frame = true;
872 PerformTestWithLeftRightRects(html_rect_size,
873 copy_rect,
874 output_size,
Ben Murdoch558790d2013-07-30 15:19:42 +0100875 video_frame);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100876}
877
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100878IN_PROC_BROWSER_TEST_P(
879 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
880 MAYBE_CopyToVideoFrame_CenterRegion) {
881 gfx::Size html_rect_size(200, 150);
882 // Grab 90x60 pixels from the center of the tab contents.
883 gfx::Rect copy_rect =
884 gfx::Rect(gfx::Rect(html_rect_size).CenterPoint() - gfx::Vector2d(45, 30),
885 gfx::Size(90, 60));
886 // Scale the output size so that, internally, scaling is not occurring.
887 gfx::Size output_size =
888 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
889 bool video_frame = true;
890 PerformTestWithLeftRightRects(html_rect_size,
891 copy_rect,
892 output_size,
893 video_frame);
894}
895
896IN_PROC_BROWSER_TEST_P(
897 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
898 MAYBE_CopyToVideoFrame_ScaledResult) {
899 gfx::Size html_rect_size(200, 100);
900 gfx::Rect copy_rect(200, 100);
901 // Output is being down-scaled since output_size is in phyiscal pixels.
902 gfx::Size output_size(200, 100);
903 bool video_frame = true;
904 PerformTestWithLeftRightRects(html_rect_size,
905 copy_rect,
906 output_size,
907 video_frame);
908}
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000909
910INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
911 CompositingRenderWidgetHostViewBrowserTest,
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100912 testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000913INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
914 CompositingRenderWidgetHostViewBrowserTestTabCapture,
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100915 testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
916INSTANTIATE_TEST_CASE_P(
917 GLAndSoftwareCompositing,
918 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
919 testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000920
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100921#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
922
923} // namespace
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000924} // namespace content