blob: 8383396b5dc428eab6414a6b6de5cafe14f40cd5 [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"
13#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
14#include "content/port/browser/render_widget_host_view_port.h"
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010015#include "content/public/browser/gpu_data_manager.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000016#include "content/public/browser/render_view_host.h"
17#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"
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +010022#include "content/shell/browser/shell.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000023#include "content/test/content_browser_test.h"
24#include "content/test/content_browser_test_utils.h"
25#include "media/base/video_frame.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010026#include "media/filters/skcanvas_video_renderer.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000027#include "net/base/net_util.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010028#include "third_party/skia/include/core/SkBitmap.h"
Torne (Richard Coles)424c4d72013-08-30 15:14:49 +010029#include "third_party/skia/include/core/SkBitmapDevice.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010030#include "third_party/skia/include/core/SkCanvas.h"
Ben Murdoch558790d2013-07-30 15:19:42 +010031#include "ui/base/ui_base_switches.h"
Ben Murdoch558790d2013-07-30 15:19:42 +010032#include "ui/gfx/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
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000036#if defined(OS_MACOSX)
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010037#include "ui/gl/io_surface_support_mac.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000038#endif
39
Ben Murdoch558790d2013-07-30 15:19:42 +010040#if defined(OS_WIN)
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +010041#include "base/win/windows_version.h"
42#include "ui/gfx/win/dpi.h"
Ben Murdoch558790d2013-07-30 15:19:42 +010043#endif
44
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000045namespace content {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010046namespace {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000047
Ben Murdoch558790d2013-07-30 15:19:42 +010048// Convenience macro: Short-circuit a pass for the tests where platform support
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010049// for forced-compositing mode (or disabled-compositing mode) is lacking.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010050#define SET_UP_SURFACE_OR_PASS_TEST(wait_message) \
51 if (!SetUpSourceSurface(wait_message)) { \
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010052 LOG(WARNING) \
53 << ("Blindly passing this test: This platform does not support " \
54 "forced compositing (or forced-disabled compositing) mode."); \
55 return; \
56 }
57
Ben Murdoch558790d2013-07-30 15:19:42 +010058// Convenience macro: Short-circuit a pass for platforms where setting up
59// high-DPI fails.
60#define PASS_TEST_IF_SCALE_FACTOR_NOT_SUPPORTED(factor) \
Torne (Richard Coles)68043e12013-09-26 13:24:57 +010061 if (ui::GetImageScale( \
Ben Murdoch558790d2013-07-30 15:19:42 +010062 GetScaleFactorForView(GetRenderWidgetHostViewPort())) != factor) { \
63 LOG(WARNING) << "Blindly passing this test: failed to set up " \
64 "scale factor: " << factor; \
65 return false; \
66 }
67
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010068// Common base class for browser tests. This is subclassed twice: Once to test
69// the browser in forced-compositing mode, and once to test with compositing
70// mode disabled.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000071class RenderWidgetHostViewBrowserTest : public ContentBrowserTest {
72 public:
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010073 RenderWidgetHostViewBrowserTest()
74 : frame_size_(400, 300),
75 callback_invoke_count_(0),
76 frames_captured_(0) {}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000077
78 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
79 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir_));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010080 ContentBrowserTest::SetUpInProcessBrowserTestFixture();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000081 }
82
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010083 // Attempts to set up the source surface. Returns false if unsupported on the
84 // current platform.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010085 virtual bool SetUpSourceSurface(const char* wait_message) = 0;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010086
87 int callback_invoke_count() const {
88 return callback_invoke_count_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000089 }
90
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010091 int frames_captured() const {
92 return frames_captured_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000093 }
94
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010095 const gfx::Size& frame_size() const {
96 return frame_size_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000097 }
98
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010099 const base::FilePath& test_dir() const {
100 return test_dir_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000101 }
102
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100103 RenderViewHost* GetRenderViewHost() const {
104 RenderViewHost* const rvh = shell()->web_contents()->GetRenderViewHost();
105 CHECK(rvh);
106 return rvh;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000107 }
108
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100109 RenderWidgetHostImpl* GetRenderWidgetHost() const {
110 RenderWidgetHostImpl* const rwh = RenderWidgetHostImpl::From(
111 shell()->web_contents()->GetRenderWidgetHostView()->
112 GetRenderWidgetHost());
113 CHECK(rwh);
114 return rwh;
115 }
116
117 RenderWidgetHostViewPort* GetRenderWidgetHostViewPort() const {
118 RenderWidgetHostViewPort* const view =
119 RenderWidgetHostViewPort::FromRWHV(GetRenderViewHost()->GetView());
120 CHECK(view);
121 return view;
122 }
123
124 // Callback when using CopyFromBackingStore() API.
125 void FinishCopyFromBackingStore(const base::Closure& quit_closure,
126 bool frame_captured,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000127 const SkBitmap& bitmap) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100128 ++callback_invoke_count_;
129 if (frame_captured) {
130 ++frames_captured_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000131 EXPECT_FALSE(bitmap.empty());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100132 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000133 if (!quit_closure.is_null())
134 quit_closure.Run();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100135 }
136
137 // Callback when using CopyFromCompositingSurfaceToVideoFrame() API.
138 void FinishCopyFromCompositingSurface(const base::Closure& quit_closure,
139 bool frame_captured) {
140 ++callback_invoke_count_;
141 if (frame_captured)
142 ++frames_captured_;
143 if (!quit_closure.is_null())
144 quit_closure.Run();
145 }
146
147 // Callback when using frame subscriber API.
148 void FrameDelivered(const scoped_refptr<base::MessageLoopProxy>& loop,
149 base::Closure quit_closure,
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000150 base::TimeTicks timestamp,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100151 bool frame_captured) {
152 ++callback_invoke_count_;
153 if (frame_captured)
154 ++frames_captured_;
155 if (!quit_closure.is_null())
156 loop->PostTask(FROM_HERE, quit_closure);
157 }
158
159 // Copy one frame using the CopyFromBackingStore API.
160 void RunBasicCopyFromBackingStoreTest() {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100161 SET_UP_SURFACE_OR_PASS_TEST(NULL);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100162
163 // Repeatedly call CopyFromBackingStore() since, on some platforms (e.g.,
164 // Windows), the operation will fail until the first "present" has been
165 // made.
166 int count_attempts = 0;
167 while (true) {
168 ++count_attempts;
169 base::RunLoop run_loop;
170 GetRenderViewHost()->CopyFromBackingStore(
171 gfx::Rect(),
172 frame_size(),
173 base::Bind(
174 &RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
175 base::Unretained(this),
176 run_loop.QuitClosure()));
177 run_loop.Run();
178
179 if (frames_captured())
180 break;
181 else
182 GiveItSomeTime();
183 }
184
185 EXPECT_EQ(count_attempts, callback_invoke_count());
186 EXPECT_EQ(1, frames_captured());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000187 }
188
189 protected:
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100190 // Waits until the source is available for copying.
191 void WaitForCopySourceReady() {
192 while (!GetRenderWidgetHostViewPort()->IsSurfaceAvailableForCopy())
193 GiveItSomeTime();
194 }
195
196 // Run the current message loop for a short time without unwinding the current
197 // call stack.
198 static void GiveItSomeTime() {
199 base::RunLoop run_loop;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100200 base::MessageLoop::current()->PostDelayedTask(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100201 FROM_HERE,
202 run_loop.QuitClosure(),
203 base::TimeDelta::FromMilliseconds(10));
204 run_loop.Run();
205 }
206
207 private:
208 const gfx::Size frame_size_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000209 base::FilePath test_dir_;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100210 int callback_invoke_count_;
211 int frames_captured_;
212};
213
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000214enum CompositingMode {
215 GL_COMPOSITING,
216 SOFTWARE_COMPOSITING,
217};
218
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100219class CompositingRenderWidgetHostViewBrowserTest
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000220 : public RenderWidgetHostViewBrowserTest,
221 public testing::WithParamInterface<CompositingMode> {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100222 public:
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000223 explicit CompositingRenderWidgetHostViewBrowserTest()
224 : compositing_mode_(GetParam()) {}
225
Ben Murdochc2db58b2013-08-14 11:51:42 +0100226 virtual void SetUp() OVERRIDE {
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000227 if (compositing_mode_ == SOFTWARE_COMPOSITING)
228 UseSoftwareCompositing();
Ben Murdochc2db58b2013-08-14 11:51:42 +0100229 RenderWidgetHostViewBrowserTest::SetUp();
230 }
231
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100232 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
233 // Note: Not appending kForceCompositingMode switch here, since not all bots
234 // support compositing. Some bots will run with compositing on, and others
235 // won't. Therefore, the call to SetUpSourceSurface() later on will detect
236 // whether compositing mode is actually on or not. If not, the tests will
237 // pass blindly, logging a warning message, since we cannot test what the
238 // platform/implementation does not support.
239 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line);
240 }
241
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100242 virtual GURL TestUrl() {
243 return net::FilePathToFileURL(
244 test_dir().AppendASCII("rwhv_compositing_animation.html"));
245 }
246
247 virtual bool SetUpSourceSurface(const char* wait_message) OVERRIDE {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100248 if (!IsForceCompositingModeEnabled())
249 return false; // See comment in SetUpCommandLine().
250#if defined(OS_MACOSX)
251 CHECK(IOSurfaceSupport::Initialize());
252#endif
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100253
254 content::DOMMessageQueue message_queue;
255 NavigateToURL(shell(), TestUrl());
256 if (wait_message != NULL) {
257 std::string result(wait_message);
258 if (!message_queue.WaitForMessage(&result)) {
259 EXPECT_TRUE(false) << "WaitForMessage " << result << " failed.";
260 return false;
261 }
262 }
263
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100264#if !defined(USE_AURA)
265 if (!GetRenderWidgetHost()->is_accelerated_compositing_active())
266 return false; // Renderer did not turn on accelerated compositing.
267#endif
268
269 // Using accelerated compositing, but a compositing surface might not be
270 // available yet. So, wait for it.
271 WaitForCopySourceReady();
272 return true;
273 }
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000274
275 private:
276 const CompositingMode compositing_mode_;
277
278 DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewBrowserTest);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100279};
280
281class NonCompositingRenderWidgetHostViewBrowserTest
282 : public RenderWidgetHostViewBrowserTest {
283 public:
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000284 NonCompositingRenderWidgetHostViewBrowserTest() {}
285
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100286 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
287 // Note: Appending the kDisableAcceleratedCompositing switch here, but there
288 // are some builds that only use compositing and will ignore this switch.
289 // Therefore, the call to SetUpSourceSurface() later on will detect whether
290 // compositing mode is actually off. If it's on, the tests will pass
291 // blindly, logging a warning message, since we cannot test what the
292 // platform/implementation does not support.
293 command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
294 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line);
295 }
296
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100297 virtual GURL TestUrl() {
Ben Murdoch2385ea32013-08-06 11:01:04 +0100298 return GURL(kAboutBlankURL);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100299 }
300
301 virtual bool SetUpSourceSurface(const char* wait_message) OVERRIDE {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100302 if (IsForceCompositingModeEnabled())
303 return false; // See comment in SetUpCommandLine().
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100304
305 content::DOMMessageQueue message_queue;
306 NavigateToURL(shell(), TestUrl());
307 if (wait_message != NULL) {
308 std::string result(wait_message);
309 if (!message_queue.WaitForMessage(&result)) {
310 EXPECT_TRUE(false) << "WaitForMessage " << result << " failed.";
311 return false;
312 }
313 }
314
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100315 WaitForCopySourceReady();
316 // Return whether the renderer left accelerated compositing turned off.
317 return !GetRenderWidgetHost()->is_accelerated_compositing_active();
318 }
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000319
320 private:
321 DISALLOW_COPY_AND_ASSIGN(NonCompositingRenderWidgetHostViewBrowserTest);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000322};
323
324class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
325 public:
326 FakeFrameSubscriber(
327 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback)
328 : callback_(callback) {
329 }
330
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000331 virtual bool ShouldCaptureFrame(base::TimeTicks present_time,
332 scoped_refptr<media::VideoFrame>* storage,
333 DeliverFrameCallback* callback) OVERRIDE {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100334 // Only allow one frame capture to be made. Otherwise, the compositor could
335 // start multiple captures, unbounded, and eventually its own limiter logic
336 // will begin invoking |callback| with a |false| result. This flakes out
337 // the unit tests, since they receive a "failed" callback before the later
338 // "success" callbacks.
339 if (callback_.is_null())
340 return false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000341 *storage = media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
342 *callback = callback_;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100343 callback_.Reset();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000344 return true;
345 }
346
347 private:
348 DeliverFrameCallback callback_;
349};
350
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100351// Disable tests for Android and IOS as these platforms have incomplete
352// implementation.
353#if !defined(OS_ANDROID) && !defined(OS_IOS)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000354
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100355// The CopyFromBackingStore() API should work on all platforms when compositing
356// is enabled.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000357IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100358 CopyFromBackingStore) {
359 RunBasicCopyFromBackingStoreTest();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000360}
361
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100362// The CopyFromBackingStore() API should work on all platforms when compositing
363// is disabled.
364IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest,
365 CopyFromBackingStore) {
366 RunBasicCopyFromBackingStoreTest();
367}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000368
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100369// Tests that the callback passed to CopyFromBackingStore is always called,
370// even when the RenderWidgetHost is deleting in the middle of an async copy.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000371IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100372 CopyFromBackingStore_CallbackDespiteDelete) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100373 SET_UP_SURFACE_OR_PASS_TEST(NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000374
375 base::RunLoop run_loop;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100376 GetRenderViewHost()->CopyFromBackingStore(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000377 gfx::Rect(),
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100378 frame_size(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000379 base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100380 base::Unretained(this), run_loop.QuitClosure()));
381 // Delete the surface before the callback is run.
382 GetRenderWidgetHostViewPort()->AcceleratedSurfaceRelease();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000383 run_loop.Run();
384
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100385 EXPECT_EQ(1, callback_invoke_count());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000386}
387
388// Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is
389// always called, even when the RenderWidgetHost is deleting in the middle of
390// an async copy.
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100391//
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000392// Test is flaky on Win. http://crbug.com/276783
393#if defined(OS_WIN) || (defined(OS_CHROMEOS) && !defined(NDEBUG))
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100394#define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
395 DISABLED_CopyFromCompositingSurface_CallbackDespiteDelete
396#else
397#define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
398 CopyFromCompositingSurface_CallbackDespiteDelete
399#endif
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000400IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100401 MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100402 SET_UP_SURFACE_OR_PASS_TEST(NULL);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100403 RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort();
404 if (!view->CanCopyToVideoFrame()) {
405 LOG(WARNING) <<
406 ("Blindly passing this test: CopyFromCompositingSurfaceToVideoFrame() "
407 "not supported on this platform.");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000408 return;
409 }
Ben Murdochc2db58b2013-08-14 11:51:42 +0100410
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000411 base::RunLoop run_loop;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000412 scoped_refptr<media::VideoFrame> dest =
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100413 media::VideoFrame::CreateBlackFrame(frame_size());
414 view->CopyFromCompositingSurfaceToVideoFrame(
415 gfx::Rect(view->GetViewBounds().size()), dest, base::Bind(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000416 &RenderWidgetHostViewBrowserTest::FinishCopyFromCompositingSurface,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100417 base::Unretained(this), run_loop.QuitClosure()));
418 // Delete the surface before the callback is run.
419 view->AcceleratedSurfaceRelease();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000420 run_loop.Run();
421
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100422 EXPECT_EQ(1, callback_invoke_count());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000423}
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100424
425// With compositing turned off, no platforms should support the
426// CopyFromCompositingSurfaceToVideoFrame() API.
427IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest,
428 CopyFromCompositingSurfaceToVideoFrameCallbackTest) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100429 SET_UP_SURFACE_OR_PASS_TEST(NULL);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100430 EXPECT_FALSE(GetRenderWidgetHostViewPort()->CanCopyToVideoFrame());
431}
432
433// Test basic frame subscription functionality. We subscribe, and then run
434// until at least one DeliverFrameCallback has been invoked.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000435IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100436 FrameSubscriberTest) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100437 SET_UP_SURFACE_OR_PASS_TEST(NULL);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100438 RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort();
439 if (!view->CanSubscribeFrame()) {
440 LOG(WARNING) << ("Blindly passing this test: Frame subscription not "
441 "supported on this platform.");
442 return;
443 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000444
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000445 base::RunLoop run_loop;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000446 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100447 new FakeFrameSubscriber(
448 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
449 base::Unretained(this),
450 base::MessageLoopProxy::current(),
451 run_loop.QuitClosure())));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000452 view->BeginFrameSubscription(subscriber.Pass());
453 run_loop.Run();
454 view->EndFrameSubscription();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100455
456 EXPECT_LE(1, callback_invoke_count());
457 EXPECT_LE(1, frames_captured());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000458}
459
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000460// Test that we can copy twice from an accelerated composited page.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000461IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest, CopyTwice) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100462 SET_UP_SURFACE_OR_PASS_TEST(NULL);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100463 RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort();
464 if (!view->CanCopyToVideoFrame()) {
465 LOG(WARNING) << ("Blindly passing this test: "
466 "CopyFromCompositingSurfaceToVideoFrame() not supported "
467 "on this platform.");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000468 return;
469 }
470
471 base::RunLoop run_loop;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100472 scoped_refptr<media::VideoFrame> first_output =
473 media::VideoFrame::CreateBlackFrame(frame_size());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100474 ASSERT_TRUE(first_output.get());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100475 scoped_refptr<media::VideoFrame> second_output =
476 media::VideoFrame::CreateBlackFrame(frame_size());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100477 ASSERT_TRUE(second_output.get());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100478 view->CopyFromCompositingSurfaceToVideoFrame(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100479 gfx::Rect(view->GetViewBounds().size()),
480 first_output,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100481 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
482 base::Unretained(this),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000483 base::MessageLoopProxy::current(),
484 base::Closure(),
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000485 base::TimeTicks::Now()));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100486 view->CopyFromCompositingSurfaceToVideoFrame(
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000487 gfx::Rect(view->GetViewBounds().size()),
488 second_output,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100489 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
490 base::Unretained(this),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000491 base::MessageLoopProxy::current(),
492 run_loop.QuitClosure(),
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000493 base::TimeTicks::Now()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000494 run_loop.Run();
495
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100496 EXPECT_EQ(2, callback_invoke_count());
497 EXPECT_EQ(2, frames_captured());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000498}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000499
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100500class CompositingRenderWidgetHostViewBrowserTestTabCapture
501 : public CompositingRenderWidgetHostViewBrowserTest {
502 public:
503 CompositingRenderWidgetHostViewBrowserTestTabCapture()
504 : expected_copy_from_compositing_surface_result_(false),
505 allowable_error_(0),
506 test_url_("data:text/html,<!doctype html>") {}
507
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000508 virtual void SetUp() OVERRIDE {
509 EnablePixelOutput();
510 CompositingRenderWidgetHostViewBrowserTest::SetUp();
511 }
512
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100513 void CopyFromCompositingSurfaceCallback(base::Closure quit_callback,
514 bool result,
515 const SkBitmap& bitmap) {
516 EXPECT_EQ(expected_copy_from_compositing_surface_result_, result);
517 if (!result) {
518 quit_callback.Run();
519 return;
520 }
521
522 const SkBitmap& expected_bitmap =
523 expected_copy_from_compositing_surface_bitmap_;
524 EXPECT_EQ(expected_bitmap.width(), bitmap.width());
525 EXPECT_EQ(expected_bitmap.height(), bitmap.height());
526 EXPECT_EQ(expected_bitmap.config(), bitmap.config());
527 SkAutoLockPixels expected_bitmap_lock(expected_bitmap);
528 SkAutoLockPixels bitmap_lock(bitmap);
529 int fails = 0;
530 for (int i = 0; i < bitmap.width() && fails < 10; ++i) {
531 for (int j = 0; j < bitmap.height() && fails < 10; ++j) {
532 if (!exclude_rect_.IsEmpty() && exclude_rect_.Contains(i, j))
533 continue;
534
535 SkColor expected_color = expected_bitmap.getColor(i, j);
536 SkColor color = bitmap.getColor(i, j);
537 int expected_alpha = SkColorGetA(expected_color);
538 int alpha = SkColorGetA(color);
539 int expected_red = SkColorGetR(expected_color);
540 int red = SkColorGetR(color);
541 int expected_green = SkColorGetG(expected_color);
542 int green = SkColorGetG(color);
543 int expected_blue = SkColorGetB(expected_color);
544 int blue = SkColorGetB(color);
545 EXPECT_NEAR(expected_alpha, alpha, allowable_error_)
546 << "expected_color: " << std::hex << expected_color
547 << " color: " << color
548 << " Failed at " << std::dec << i << ", " << j
549 << " Failure " << ++fails;
550 EXPECT_NEAR(expected_red, red, allowable_error_)
551 << "expected_color: " << std::hex << expected_color
552 << " color: " << color
553 << " Failed at " << std::dec << i << ", " << j
554 << " Failure " << ++fails;
555 EXPECT_NEAR(expected_green, green, allowable_error_)
556 << "expected_color: " << std::hex << expected_color
557 << " color: " << color
558 << " Failed at " << std::dec << i << ", " << j
559 << " Failure " << ++fails;
560 EXPECT_NEAR(expected_blue, blue, allowable_error_)
561 << "expected_color: " << std::hex << expected_color
562 << " color: " << color
563 << " Failed at " << std::dec << i << ", " << j
564 << " Failure " << ++fails;
565 }
566 }
567 EXPECT_LT(fails, 10);
568
569 quit_callback.Run();
570 }
571
572 void CopyFromCompositingSurfaceCallbackForVideo(
573 scoped_refptr<media::VideoFrame> video_frame,
574 base::Closure quit_callback,
575 bool result) {
576 EXPECT_EQ(expected_copy_from_compositing_surface_result_, result);
577 if (!result) {
578 quit_callback.Run();
579 return;
580 }
581
582 media::SkCanvasVideoRenderer video_renderer;
583
584 SkBitmap bitmap;
585 bitmap.setConfig(SkBitmap::kARGB_8888_Config,
586 video_frame->visible_rect().width(),
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000587 video_frame->visible_rect().height(),
588 0, kOpaque_SkAlphaType);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100589 bitmap.allocPixels();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100590
Torne (Richard Coles)424c4d72013-08-30 15:14:49 +0100591 SkBitmapDevice device(bitmap);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100592 SkCanvas canvas(&device);
593
594 video_renderer.Paint(video_frame.get(),
595 &canvas,
596 video_frame->visible_rect(),
597 0xff);
598
599 CopyFromCompositingSurfaceCallback(quit_callback,
600 result,
601 bitmap);
602 }
603
604 void SetExpectedCopyFromCompositingSurfaceResult(bool result,
605 const SkBitmap& bitmap) {
606 expected_copy_from_compositing_surface_result_ = result;
607 expected_copy_from_compositing_surface_bitmap_ = bitmap;
608 }
609
610 void SetAllowableError(int amount) { allowable_error_ = amount; }
611 void SetExcludeRect(gfx::Rect exclude) { exclude_rect_ = exclude; }
612
613 virtual GURL TestUrl() OVERRIDE {
614 return GURL(test_url_);
615 }
616
617 void SetTestUrl(std::string url) { test_url_ = url; }
618
Ben Murdoch558790d2013-07-30 15:19:42 +0100619 // Loads a page two boxes side-by-side, each half the width of
620 // |html_rect_size|, and with different background colors. The test then
621 // copies from |copy_rect| region of the page into a bitmap of size
622 // |output_size|, and compares that with a bitmap of size
623 // |expected_bitmap_size|.
624 // Note that |output_size| may not have the same size as |copy_rect| (e.g.
625 // when the output is scaled). Also note that |expected_bitmap_size| may not
626 // be the same as |output_size| (e.g. when the device scale factor is not 1).
627 void PerformTestWithLeftRightRects(const gfx::Size& html_rect_size,
628 const gfx::Rect& copy_rect,
629 const gfx::Size& output_size,
630 const gfx::Size& expected_bitmap_size,
631 bool video_frame) {
632 const gfx::Size box_size(html_rect_size.width() / 2,
633 html_rect_size.height());
634 SetTestUrl(base::StringPrintf(
635 "data:text/html,<!doctype html>"
636 "<div class='left'>"
637 " <div class='right'></div>"
638 "</div>"
639 "<style>"
640 "body { padding: 0; margin: 0; }"
641 ".left { position: absolute;"
642 " background: #0ff;"
643 " width: %dpx;"
644 " height: %dpx;"
645 "}"
646 ".right { position: absolute;"
647 " left: %dpx;"
648 " background: #ff0;"
649 " width: %dpx;"
650 " height: %dpx;"
651 "}"
652 "</style>"
653 "<script>"
654 " domAutomationController.setAutomationId(0);"
655 " domAutomationController.send(\"DONE\");"
656 "</script>",
657 box_size.width(),
658 box_size.height(),
659 box_size.width(),
660 box_size.width(),
661 box_size.height()));
662
663 SET_UP_SURFACE_OR_PASS_TEST("\"DONE\"");
664 if (!ShouldContinueAfterTestURLLoad())
665 return;
666
667 RenderWidgetHostViewPort* rwhvp = GetRenderWidgetHostViewPort();
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000668 if (video_frame && !rwhvp->CanCopyToVideoFrame()) {
669 // This should only happen on Mac when using the software compositor.
670 // Otherwise, raise an error. This can be removed when Mac is moved to a
671 // browser compositor.
672 // http://crbug.com/314190
673#if defined(OS_MACOSX)
674 if (!content::GpuDataManager::GetInstance()->GpuAccessAllowed(NULL)) {
675 LOG(WARNING) << ("Blindly passing this test because copying to "
676 "video frames is not supported on this platform.");
677 return;
678 }
679#endif
680 NOTREACHED();
681 }
Ben Murdoch558790d2013-07-30 15:19:42 +0100682
683 // The page is loaded in the renderer, wait for a new frame to arrive.
684 uint32 frame = rwhvp->RendererFrameNumber();
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +0100685 while (!GetRenderWidgetHost()->ScheduleComposite())
686 GiveItSomeTime();
Ben Murdoch558790d2013-07-30 15:19:42 +0100687 while (rwhvp->RendererFrameNumber() == frame)
688 GiveItSomeTime();
689
690 SkBitmap expected_bitmap;
691 SetupLeftRightBitmap(expected_bitmap_size, &expected_bitmap);
692 SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap);
693
694 base::RunLoop run_loop;
695 if (video_frame) {
696 // Allow pixel differences as long as we have the right idea.
697 SetAllowableError(0x10);
698 // Exclude the middle two columns which are blended between the two sides.
699 SetExcludeRect(
700 gfx::Rect(output_size.width() / 2 - 1, 0, 2, output_size.height()));
701
702 scoped_refptr<media::VideoFrame> video_frame =
703 media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
Ben Murdochd3868032013-07-31 10:55:33 +0100704 expected_bitmap_size,
705 gfx::Rect(expected_bitmap_size),
706 expected_bitmap_size,
Ben Murdoch558790d2013-07-30 15:19:42 +0100707 base::TimeDelta());
708
709 base::Callback<void(bool success)> callback =
710 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
711 CopyFromCompositingSurfaceCallbackForVideo,
712 base::Unretained(this),
713 video_frame,
714 run_loop.QuitClosure());
715 rwhvp->CopyFromCompositingSurfaceToVideoFrame(copy_rect,
716 video_frame,
717 callback);
718 } else {
Torne (Richard Coles)8bcbed82013-10-22 16:41:35 +0100719#if defined(USE_AURA)
720 if (!content::GpuDataManager::GetInstance()
721 ->CanUseGpuBrowserCompositor()) {
722 // Skia rendering can cause color differences, particularly in the
723 // middle two columns.
724 SetAllowableError(2);
725 SetExcludeRect(
726 gfx::Rect(output_size.width() / 2 - 1, 0, 2, output_size.height()));
727 }
728#endif
729
Ben Murdoch558790d2013-07-30 15:19:42 +0100730 base::Callback<void(bool, const SkBitmap&)> callback =
731 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
732 CopyFromCompositingSurfaceCallback,
733 base::Unretained(this),
734 run_loop.QuitClosure());
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000735 rwhvp->CopyFromCompositingSurface(copy_rect,
736 output_size,
737 callback,
738 SkBitmap::kARGB_8888_Config);
Ben Murdoch558790d2013-07-30 15:19:42 +0100739 }
740 run_loop.Run();
741 }
742
743 // Sets up |bitmap| to have size |copy_size|. It floods the left half with
744 // #0ff and the right half with #ff0.
745 void SetupLeftRightBitmap(const gfx::Size& copy_size, SkBitmap* bitmap) {
746 bitmap->setConfig(
747 SkBitmap::kARGB_8888_Config, copy_size.width(), copy_size.height());
748 bitmap->allocPixels();
749 // Left half is #0ff.
750 bitmap->eraseARGB(255, 0, 255, 255);
751 // Right half is #ff0.
752 {
753 SkAutoLockPixels lock(*bitmap);
754 for (int i = 0; i < copy_size.width() / 2; ++i) {
755 for (int j = 0; j < copy_size.height(); ++j) {
756 *(bitmap->getAddr32(copy_size.width() / 2 + i, j)) =
757 SkColorSetARGB(255, 255, 255, 0);
758 }
759 }
760 }
761 }
762
763 protected:
764 virtual bool ShouldContinueAfterTestURLLoad() {
765 return true;
766 }
767
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100768 private:
769 bool expected_copy_from_compositing_surface_result_;
770 SkBitmap expected_copy_from_compositing_surface_bitmap_;
771 int allowable_error_;
772 gfx::Rect exclude_rect_;
773 std::string test_url_;
774};
775
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000776IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100777 CopyFromCompositingSurface_Origin_Unscaled) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100778 gfx::Rect copy_rect(400, 300);
779 gfx::Size output_size = copy_rect.size();
780 gfx::Size expected_bitmap_size = output_size;
781 gfx::Size html_rect_size(400, 300);
782 bool video_frame = false;
783 PerformTestWithLeftRightRects(html_rect_size,
784 copy_rect,
785 output_size,
786 expected_bitmap_size,
787 video_frame);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100788}
789
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000790IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100791 CopyFromCompositingSurface_Origin_Scaled) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100792 gfx::Rect copy_rect(400, 300);
793 gfx::Size output_size(200, 100);
794 gfx::Size expected_bitmap_size = output_size;
795 gfx::Size html_rect_size(400, 300);
796 bool video_frame = false;
797 PerformTestWithLeftRightRects(html_rect_size,
798 copy_rect,
799 output_size,
800 expected_bitmap_size,
801 video_frame);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100802}
803
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000804IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100805 CopyFromCompositingSurface_Cropped_Unscaled) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100806 // Grab 60x60 pixels from the center of the tab contents.
Ben Murdoch558790d2013-07-30 15:19:42 +0100807 gfx::Rect copy_rect(400, 300);
808 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
809 gfx::Size(60, 60));
810 gfx::Size output_size = copy_rect.size();
811 gfx::Size expected_bitmap_size = output_size;
812 gfx::Size html_rect_size(400, 300);
813 bool video_frame = false;
814 PerformTestWithLeftRightRects(html_rect_size,
815 copy_rect,
816 output_size,
817 expected_bitmap_size,
818 video_frame);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100819}
820
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000821IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100822 CopyFromCompositingSurface_Cropped_Scaled) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100823 // Grab 60x60 pixels from the center of the tab contents.
Ben Murdoch558790d2013-07-30 15:19:42 +0100824 gfx::Rect copy_rect(400, 300);
825 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
826 gfx::Size(60, 60));
827 gfx::Size output_size(20, 10);
828 gfx::Size expected_bitmap_size = output_size;
829 gfx::Size html_rect_size(400, 300);
830 bool video_frame = false;
831 PerformTestWithLeftRightRects(html_rect_size,
832 copy_rect,
833 output_size,
834 expected_bitmap_size,
835 video_frame);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100836}
837
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000838IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100839 CopyFromCompositingSurface_ForVideoFrame) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100840 // Grab 90x60 pixels from the center of the tab contents.
Ben Murdoch558790d2013-07-30 15:19:42 +0100841 gfx::Rect copy_rect(400, 300);
842 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(45, 30),
843 gfx::Size(90, 60));
844 gfx::Size output_size = copy_rect.size();
845 gfx::Size expected_bitmap_size = output_size;
846 gfx::Size html_rect_size(400, 300);
847 bool video_frame = true;
848 PerformTestWithLeftRightRects(html_rect_size,
849 copy_rect,
850 output_size,
851 expected_bitmap_size,
852 video_frame);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100853}
854
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000855IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100856 CopyFromCompositingSurface_ForVideoFrame_Scaled) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100857 // Grab 90x60 pixels from the center of the tab contents.
Ben Murdoch558790d2013-07-30 15:19:42 +0100858 gfx::Rect copy_rect(400, 300);
859 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(45, 30),
860 gfx::Size(90, 60));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100861 // Scale to 30 x 20 (preserve aspect ratio).
Ben Murdoch558790d2013-07-30 15:19:42 +0100862 gfx::Size output_size(30, 20);
863 gfx::Size expected_bitmap_size = output_size;
864 gfx::Size html_rect_size(400, 300);
865 bool video_frame = true;
866 PerformTestWithLeftRightRects(html_rect_size,
867 copy_rect,
868 output_size,
869 expected_bitmap_size,
870 video_frame);
871}
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100872
Ben Murdoch558790d2013-07-30 15:19:42 +0100873class CompositingRenderWidgetHostViewTabCaptureHighDPI
874 : public CompositingRenderWidgetHostViewBrowserTestTabCapture {
875 public:
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000876 CompositingRenderWidgetHostViewTabCaptureHighDPI() : kScale(2.f) {}
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100877
Ben Murdoch558790d2013-07-30 15:19:42 +0100878 virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE {
879 CompositingRenderWidgetHostViewBrowserTestTabCapture::SetUpCommandLine(cmd);
880 cmd->AppendSwitchASCII(switches::kForceDeviceScaleFactor,
881 base::StringPrintf("%f", scale()));
882#if defined(OS_WIN)
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100883 cmd->AppendSwitchASCII(switches::kHighDPISupport, "1");
Torne (Richard Coles)58537e22013-09-12 12:10:22 +0100884 gfx::EnableHighDPISupport();
Ben Murdoch558790d2013-07-30 15:19:42 +0100885#endif
886 }
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100887
Ben Murdoch558790d2013-07-30 15:19:42 +0100888 float scale() const { return kScale; }
889
890 private:
891 virtual bool ShouldContinueAfterTestURLLoad() OVERRIDE {
892 PASS_TEST_IF_SCALE_FACTOR_NOT_SUPPORTED(scale());
893 return true;
894 }
895
896 const float kScale;
897
898 DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewTabCaptureHighDPI);
899};
900
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000901IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewTabCaptureHighDPI,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100902 CopyFromCompositingSurface) {
Ben Murdoch558790d2013-07-30 15:19:42 +0100903 gfx::Rect copy_rect(200, 150);
Ben Murdochd3868032013-07-31 10:55:33 +0100904 gfx::Size output_size = copy_rect.size();
905 gfx::Size expected_bitmap_size =
906 gfx::ToFlooredSize(gfx::ScaleSize(output_size, scale(), scale()));
Ben Murdoch558790d2013-07-30 15:19:42 +0100907 gfx::Size html_rect_size(200, 150);
908 bool video_frame = false;
909 PerformTestWithLeftRightRects(html_rect_size,
910 copy_rect,
Ben Murdochd3868032013-07-31 10:55:33 +0100911 output_size,
912 expected_bitmap_size,
913 video_frame);
914}
915
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000916IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewTabCaptureHighDPI,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100917 CopyFromCompositingSurfaceVideoFrame) {
Ben Murdochd3868032013-07-31 10:55:33 +0100918 gfx::Size html_rect_size(200, 150);
919 // Grab 90x60 pixels from the center of the tab contents.
920 gfx::Rect copy_rect =
921 gfx::Rect(gfx::Rect(html_rect_size).CenterPoint() - gfx::Vector2d(45, 30),
922 gfx::Size(90, 60));
923 gfx::Size output_size = copy_rect.size();
924 gfx::Size expected_bitmap_size =
925 gfx::ToFlooredSize(gfx::ScaleSize(output_size, scale(), scale()));
926 bool video_frame = true;
927 PerformTestWithLeftRightRects(html_rect_size,
928 copy_rect,
929 output_size,
Ben Murdoch558790d2013-07-30 15:19:42 +0100930 expected_bitmap_size,
931 video_frame);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100932}
933
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000934#if !defined(USE_AURA) && !defined(OS_MACOSX)
935// TODO(danakj): Remove this case when GTK linux is no more and move the
936// values inline to testing::Values() below.
937static const CompositingMode kAllCompositingModes[] = {GL_COMPOSITING};
938#else
939static const CompositingMode kAllCompositingModes[] = {GL_COMPOSITING,
940 SOFTWARE_COMPOSITING};
941#endif
942
943INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
944 CompositingRenderWidgetHostViewBrowserTest,
945 testing::ValuesIn(kAllCompositingModes));
946INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
947 CompositingRenderWidgetHostViewBrowserTestTabCapture,
948 testing::ValuesIn(kAllCompositingModes));
949INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
950 CompositingRenderWidgetHostViewTabCaptureHighDPI,
951 testing::ValuesIn(kAllCompositingModes));
952
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100953#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
954
955} // namespace
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000956} // namespace content