OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/command_line.h" | 5 #include "base/command_line.h" |
6 #include "base/message_loop/message_loop_proxy.h" | 6 #include "base/message_loop/message_loop_proxy.h" |
7 #include "base/path_service.h" | 7 #include "base/path_service.h" |
8 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
9 #include "content/browser/gpu/gpu_data_manager_impl.h" | 9 #include "content/browser/gpu/gpu_data_manager_impl.h" |
10 #include "content/browser/renderer_host/render_widget_host_impl.h" | 10 #include "content/browser/renderer_host/render_widget_host_impl.h" |
11 #include "content/port/browser/render_widget_host_view_frame_subscriber.h" | 11 #include "content/port/browser/render_widget_host_view_frame_subscriber.h" |
12 #include "content/port/browser/render_widget_host_view_port.h" | 12 #include "content/port/browser/render_widget_host_view_port.h" |
13 #include "content/public/browser/compositor_util.h" | 13 #include "content/public/browser/compositor_util.h" |
14 #include "content/public/browser/render_view_host.h" | 14 #include "content/public/browser/render_view_host.h" |
15 #include "content/public/browser/web_contents.h" | 15 #include "content/public/browser/web_contents.h" |
16 #include "content/public/common/content_paths.h" | 16 #include "content/public/common/content_paths.h" |
17 #include "content/public/common/content_switches.h" | 17 #include "content/public/common/content_switches.h" |
| 18 #include "content/public/test/browser_test_utils.h" |
18 #include "content/shell/shell.h" | 19 #include "content/shell/shell.h" |
19 #include "content/test/content_browser_test.h" | 20 #include "content/test/content_browser_test.h" |
20 #include "content/test/content_browser_test_utils.h" | 21 #include "content/test/content_browser_test_utils.h" |
21 #include "media/base/video_frame.h" | 22 #include "media/base/video_frame.h" |
22 #include "net/base/net_util.h" | 23 #include "net/base/net_util.h" |
23 #include "ui/compositor/compositor_setup.h" | 24 #include "ui/compositor/compositor_setup.h" |
| 25 #include "ui/gl/gl_switches.h" |
24 | 26 |
25 #if defined(OS_MACOSX) | 27 #if defined(OS_MACOSX) |
26 #include "ui/gl/io_surface_support_mac.h" | 28 #include "ui/gl/io_surface_support_mac.h" |
27 #endif | 29 #endif |
28 | 30 |
29 namespace content { | 31 namespace content { |
30 namespace { | 32 namespace { |
31 | 33 |
32 // Convenience macro: Short-cicuit a pass for the tests where platform support | 34 // Convenience macro: Short-cicuit a pass for the tests where platform support |
33 // for forced-compositing mode (or disabled-compositing mode) is lacking. | 35 // for forced-compositing mode (or disabled-compositing mode) is lacking. |
34 #define SET_UP_SURFACE_OR_PASS_TEST() \ | 36 #define SET_UP_SURFACE_OR_PASS_TEST(wait_message) \ |
35 if (!SetUpSourceSurface()) { \ | 37 if (!SetUpSourceSurface(wait_message)) { \ |
36 LOG(WARNING) \ | 38 LOG(WARNING) \ |
37 << ("Blindly passing this test: This platform does not support " \ | 39 << ("Blindly passing this test: This platform does not support " \ |
38 "forced compositing (or forced-disabled compositing) mode."); \ | 40 "forced compositing (or forced-disabled compositing) mode."); \ |
39 return; \ | 41 return; \ |
40 } | 42 } |
41 | 43 |
42 // Common base class for browser tests. This is subclassed twice: Once to test | 44 // Common base class for browser tests. This is subclassed twice: Once to test |
43 // the browser in forced-compositing mode, and once to test with compositing | 45 // the browser in forced-compositing mode, and once to test with compositing |
44 // mode disabled. | 46 // mode disabled. |
45 class RenderWidgetHostViewBrowserTest : public ContentBrowserTest { | 47 class RenderWidgetHostViewBrowserTest : public ContentBrowserTest { |
46 public: | 48 public: |
47 RenderWidgetHostViewBrowserTest() | 49 RenderWidgetHostViewBrowserTest() |
48 : frame_size_(400, 300), | 50 : frame_size_(400, 300), |
49 callback_invoke_count_(0), | 51 callback_invoke_count_(0), |
50 frames_captured_(0) {} | 52 frames_captured_(0) {} |
51 | 53 |
52 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { | 54 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { |
53 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir_)); | 55 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir_)); |
54 ContentBrowserTest::SetUpInProcessBrowserTestFixture(); | 56 ContentBrowserTest::SetUpInProcessBrowserTestFixture(); |
55 } | 57 } |
56 | 58 |
57 // Attempts to set up the source surface. Returns false if unsupported on the | 59 // Attempts to set up the source surface. Returns false if unsupported on the |
58 // current platform. | 60 // current platform. |
59 virtual bool SetUpSourceSurface() = 0; | 61 virtual bool SetUpSourceSurface(const char* wait_message) = 0; |
60 | 62 |
61 int callback_invoke_count() const { | 63 int callback_invoke_count() const { |
62 return callback_invoke_count_; | 64 return callback_invoke_count_; |
63 } | 65 } |
64 | 66 |
65 int frames_captured() const { | 67 int frames_captured() const { |
66 return frames_captured_; | 68 return frames_captured_; |
67 } | 69 } |
68 | 70 |
69 const gfx::Size& frame_size() const { | 71 const gfx::Size& frame_size() const { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 bool frame_captured) { | 127 bool frame_captured) { |
126 ++callback_invoke_count_; | 128 ++callback_invoke_count_; |
127 if (frame_captured) | 129 if (frame_captured) |
128 ++frames_captured_; | 130 ++frames_captured_; |
129 if (!quit_closure.is_null()) | 131 if (!quit_closure.is_null()) |
130 loop->PostTask(FROM_HERE, quit_closure); | 132 loop->PostTask(FROM_HERE, quit_closure); |
131 } | 133 } |
132 | 134 |
133 // Copy one frame using the CopyFromBackingStore API. | 135 // Copy one frame using the CopyFromBackingStore API. |
134 void RunBasicCopyFromBackingStoreTest() { | 136 void RunBasicCopyFromBackingStoreTest() { |
135 SET_UP_SURFACE_OR_PASS_TEST(); | 137 SET_UP_SURFACE_OR_PASS_TEST(NULL); |
136 | 138 |
137 // Repeatedly call CopyFromBackingStore() since, on some platforms (e.g., | 139 // Repeatedly call CopyFromBackingStore() since, on some platforms (e.g., |
138 // Windows), the operation will fail until the first "present" has been | 140 // Windows), the operation will fail until the first "present" has been |
139 // made. | 141 // made. |
140 int count_attempts = 0; | 142 int count_attempts = 0; |
141 while (true) { | 143 while (true) { |
142 ++count_attempts; | 144 ++count_attempts; |
143 base::RunLoop run_loop; | 145 base::RunLoop run_loop; |
144 GetRenderViewHost()->CopyFromBackingStore( | 146 GetRenderViewHost()->CopyFromBackingStore( |
145 gfx::Rect(), | 147 gfx::Rect(), |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | 193 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
192 // Note: Not appending kForceCompositingMode switch here, since not all bots | 194 // Note: Not appending kForceCompositingMode switch here, since not all bots |
193 // support compositing. Some bots will run with compositing on, and others | 195 // support compositing. Some bots will run with compositing on, and others |
194 // won't. Therefore, the call to SetUpSourceSurface() later on will detect | 196 // won't. Therefore, the call to SetUpSourceSurface() later on will detect |
195 // whether compositing mode is actually on or not. If not, the tests will | 197 // whether compositing mode is actually on or not. If not, the tests will |
196 // pass blindly, logging a warning message, since we cannot test what the | 198 // pass blindly, logging a warning message, since we cannot test what the |
197 // platform/implementation does not support. | 199 // platform/implementation does not support. |
198 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line); | 200 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line); |
199 } | 201 } |
200 | 202 |
201 virtual bool SetUpSourceSurface() OVERRIDE { | 203 virtual GURL TestUrl() { |
| 204 return net::FilePathToFileURL( |
| 205 test_dir().AppendASCII("rwhv_compositing_animation.html")); |
| 206 } |
| 207 |
| 208 virtual bool SetUpSourceSurface(const char* wait_message) OVERRIDE { |
202 if (!IsForceCompositingModeEnabled()) | 209 if (!IsForceCompositingModeEnabled()) |
203 return false; // See comment in SetUpCommandLine(). | 210 return false; // See comment in SetUpCommandLine(). |
204 #if defined(OS_MACOSX) | 211 #if defined(OS_MACOSX) |
205 CHECK(IOSurfaceSupport::Initialize()); | 212 CHECK(IOSurfaceSupport::Initialize()); |
206 #endif | 213 #endif |
207 NavigateToURL(shell(), net::FilePathToFileURL( | 214 |
208 test_dir().AppendASCII("rwhv_compositing_animation.html"))); | 215 content::DOMMessageQueue message_queue; |
| 216 NavigateToURL(shell(), TestUrl()); |
| 217 if (wait_message != NULL) { |
| 218 std::string result(wait_message); |
| 219 if (!message_queue.WaitForMessage(&result)) { |
| 220 EXPECT_TRUE(false) << "WaitForMessage " << result << " failed."; |
| 221 return false; |
| 222 } |
| 223 } |
| 224 |
209 #if !defined(USE_AURA) | 225 #if !defined(USE_AURA) |
210 if (!GetRenderWidgetHost()->is_accelerated_compositing_active()) | 226 if (!GetRenderWidgetHost()->is_accelerated_compositing_active()) |
211 return false; // Renderer did not turn on accelerated compositing. | 227 return false; // Renderer did not turn on accelerated compositing. |
212 #endif | 228 #endif |
213 | 229 |
214 // Using accelerated compositing, but a compositing surface might not be | 230 // Using accelerated compositing, but a compositing surface might not be |
215 // available yet. So, wait for it. | 231 // available yet. So, wait for it. |
216 WaitForCopySourceReady(); | 232 WaitForCopySourceReady(); |
217 return true; | 233 return true; |
218 } | 234 } |
219 }; | 235 }; |
220 | 236 |
221 class NonCompositingRenderWidgetHostViewBrowserTest | 237 class NonCompositingRenderWidgetHostViewBrowserTest |
222 : public RenderWidgetHostViewBrowserTest { | 238 : public RenderWidgetHostViewBrowserTest { |
223 public: | 239 public: |
224 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | 240 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
225 // Note: Appending the kDisableAcceleratedCompositing switch here, but there | 241 // Note: Appending the kDisableAcceleratedCompositing switch here, but there |
226 // are some builds that only use compositing and will ignore this switch. | 242 // are some builds that only use compositing and will ignore this switch. |
227 // Therefore, the call to SetUpSourceSurface() later on will detect whether | 243 // Therefore, the call to SetUpSourceSurface() later on will detect whether |
228 // compositing mode is actually off. If it's on, the tests will pass | 244 // compositing mode is actually off. If it's on, the tests will pass |
229 // blindly, logging a warning message, since we cannot test what the | 245 // blindly, logging a warning message, since we cannot test what the |
230 // platform/implementation does not support. | 246 // platform/implementation does not support. |
231 command_line->AppendSwitch(switches::kDisableAcceleratedCompositing); | 247 command_line->AppendSwitch(switches::kDisableAcceleratedCompositing); |
232 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line); | 248 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line); |
233 } | 249 } |
234 | 250 |
235 virtual bool SetUpSourceSurface() OVERRIDE { | 251 virtual GURL TestUrl() { |
| 252 return GURL("about:blank"); |
| 253 } |
| 254 |
| 255 virtual bool SetUpSourceSurface(const char* wait_message) OVERRIDE { |
236 if (IsForceCompositingModeEnabled()) | 256 if (IsForceCompositingModeEnabled()) |
237 return false; // See comment in SetUpCommandLine(). | 257 return false; // See comment in SetUpCommandLine(). |
238 NavigateToURL(shell(), GURL("about:blank")); | 258 |
| 259 content::DOMMessageQueue message_queue; |
| 260 NavigateToURL(shell(), TestUrl()); |
| 261 if (wait_message != NULL) { |
| 262 std::string result(wait_message); |
| 263 if (!message_queue.WaitForMessage(&result)) { |
| 264 EXPECT_TRUE(false) << "WaitForMessage " << result << " failed."; |
| 265 return false; |
| 266 } |
| 267 } |
| 268 |
239 WaitForCopySourceReady(); | 269 WaitForCopySourceReady(); |
240 // Return whether the renderer left accelerated compositing turned off. | 270 // Return whether the renderer left accelerated compositing turned off. |
241 return !GetRenderWidgetHost()->is_accelerated_compositing_active(); | 271 return !GetRenderWidgetHost()->is_accelerated_compositing_active(); |
242 } | 272 } |
243 }; | 273 }; |
244 | 274 |
245 class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber { | 275 class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber { |
246 public: | 276 public: |
247 FakeFrameSubscriber( | 277 FakeFrameSubscriber( |
248 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback) | 278 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback) |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 // is disabled. | 315 // is disabled. |
286 IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest, | 316 IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest, |
287 CopyFromBackingStore) { | 317 CopyFromBackingStore) { |
288 RunBasicCopyFromBackingStoreTest(); | 318 RunBasicCopyFromBackingStoreTest(); |
289 } | 319 } |
290 | 320 |
291 // Tests that the callback passed to CopyFromBackingStore is always called, | 321 // Tests that the callback passed to CopyFromBackingStore is always called, |
292 // even when the RenderWidgetHost is deleting in the middle of an async copy. | 322 // even when the RenderWidgetHost is deleting in the middle of an async copy. |
293 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest, | 323 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest, |
294 CopyFromBackingStore_CallbackDespiteDelete) { | 324 CopyFromBackingStore_CallbackDespiteDelete) { |
295 SET_UP_SURFACE_OR_PASS_TEST(); | 325 SET_UP_SURFACE_OR_PASS_TEST(NULL); |
296 | 326 |
297 base::RunLoop run_loop; | 327 base::RunLoop run_loop; |
298 GetRenderViewHost()->CopyFromBackingStore( | 328 GetRenderViewHost()->CopyFromBackingStore( |
299 gfx::Rect(), | 329 gfx::Rect(), |
300 frame_size(), | 330 frame_size(), |
301 base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore, | 331 base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore, |
302 base::Unretained(this), run_loop.QuitClosure())); | 332 base::Unretained(this), run_loop.QuitClosure())); |
303 // Delete the surface before the callback is run. | 333 // Delete the surface before the callback is run. |
304 GetRenderWidgetHostViewPort()->AcceleratedSurfaceRelease(); | 334 GetRenderWidgetHostViewPort()->AcceleratedSurfaceRelease(); |
305 run_loop.Run(); | 335 run_loop.Run(); |
306 | 336 |
307 EXPECT_EQ(1, callback_invoke_count()); | 337 EXPECT_EQ(1, callback_invoke_count()); |
308 } | 338 } |
309 | 339 |
310 // Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is | 340 // Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is |
311 // always called, even when the RenderWidgetHost is deleting in the middle of | 341 // always called, even when the RenderWidgetHost is deleting in the middle of |
312 // an async copy. | 342 // an async copy. |
313 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest, | 343 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest, |
314 CopyFromCompositingSurface_CallbackDespiteDelete) { | 344 CopyFromCompositingSurface_CallbackDespiteDelete) { |
315 SET_UP_SURFACE_OR_PASS_TEST(); | 345 SET_UP_SURFACE_OR_PASS_TEST(NULL); |
316 RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort(); | 346 RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort(); |
317 if (!view->CanCopyToVideoFrame()) { | 347 if (!view->CanCopyToVideoFrame()) { |
318 LOG(WARNING) << | 348 LOG(WARNING) << |
319 ("Blindly passing this test: CopyFromCompositingSurfaceToVideoFrame() " | 349 ("Blindly passing this test: CopyFromCompositingSurfaceToVideoFrame() " |
320 "not supported on this platform."); | 350 "not supported on this platform."); |
321 return; | 351 return; |
322 } | 352 } |
323 | 353 |
324 base::RunLoop run_loop; | 354 base::RunLoop run_loop; |
325 scoped_refptr<media::VideoFrame> dest = | 355 scoped_refptr<media::VideoFrame> dest = |
326 media::VideoFrame::CreateBlackFrame(frame_size()); | 356 media::VideoFrame::CreateBlackFrame(frame_size()); |
327 view->CopyFromCompositingSurfaceToVideoFrame( | 357 view->CopyFromCompositingSurfaceToVideoFrame( |
328 gfx::Rect(view->GetViewBounds().size()), dest, base::Bind( | 358 gfx::Rect(view->GetViewBounds().size()), dest, base::Bind( |
329 &RenderWidgetHostViewBrowserTest::FinishCopyFromCompositingSurface, | 359 &RenderWidgetHostViewBrowserTest::FinishCopyFromCompositingSurface, |
330 base::Unretained(this), run_loop.QuitClosure())); | 360 base::Unretained(this), run_loop.QuitClosure())); |
331 // Delete the surface before the callback is run. | 361 // Delete the surface before the callback is run. |
332 view->AcceleratedSurfaceRelease(); | 362 view->AcceleratedSurfaceRelease(); |
333 run_loop.Run(); | 363 run_loop.Run(); |
334 | 364 |
335 EXPECT_EQ(1, callback_invoke_count()); | 365 EXPECT_EQ(1, callback_invoke_count()); |
336 } | 366 } |
337 | 367 |
338 // With compositing turned off, no platforms should support the | 368 // With compositing turned off, no platforms should support the |
339 // CopyFromCompositingSurfaceToVideoFrame() API. | 369 // CopyFromCompositingSurfaceToVideoFrame() API. |
340 IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest, | 370 IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest, |
341 CopyFromCompositingSurfaceToVideoFrameCallbackTest) { | 371 CopyFromCompositingSurfaceToVideoFrameCallbackTest) { |
342 SET_UP_SURFACE_OR_PASS_TEST(); | 372 SET_UP_SURFACE_OR_PASS_TEST(NULL); |
343 EXPECT_FALSE(GetRenderWidgetHostViewPort()->CanCopyToVideoFrame()); | 373 EXPECT_FALSE(GetRenderWidgetHostViewPort()->CanCopyToVideoFrame()); |
344 } | 374 } |
345 | 375 |
346 // Test basic frame subscription functionality. We subscribe, and then run | 376 // Test basic frame subscription functionality. We subscribe, and then run |
347 // until at least one DeliverFrameCallback has been invoked. | 377 // until at least one DeliverFrameCallback has been invoked. |
348 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest, | 378 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest, |
349 FrameSubscriberTest) { | 379 FrameSubscriberTest) { |
350 SET_UP_SURFACE_OR_PASS_TEST(); | 380 SET_UP_SURFACE_OR_PASS_TEST(NULL); |
351 RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort(); | 381 RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort(); |
352 if (!view->CanSubscribeFrame()) { | 382 if (!view->CanSubscribeFrame()) { |
353 LOG(WARNING) << ("Blindly passing this test: Frame subscription not " | 383 LOG(WARNING) << ("Blindly passing this test: Frame subscription not " |
354 "supported on this platform."); | 384 "supported on this platform."); |
355 return; | 385 return; |
356 } | 386 } |
357 #if defined(USE_AURA) | 387 #if defined(USE_AURA) |
358 if (ui::IsTestCompositorEnabled()) { | 388 if (ui::IsTestCompositorEnabled()) { |
359 LOG(WARNING) << ("Blindly passing this test: Aura test compositor doesn't " | 389 LOG(WARNING) << ("Blindly passing this test: Aura test compositor doesn't " |
360 "support frame subscription."); | 390 "support frame subscription."); |
(...skipping 13 matching lines...) Expand all Loading... |
374 view->BeginFrameSubscription(subscriber.Pass()); | 404 view->BeginFrameSubscription(subscriber.Pass()); |
375 run_loop.Run(); | 405 run_loop.Run(); |
376 view->EndFrameSubscription(); | 406 view->EndFrameSubscription(); |
377 | 407 |
378 EXPECT_LE(1, callback_invoke_count()); | 408 EXPECT_LE(1, callback_invoke_count()); |
379 EXPECT_LE(1, frames_captured()); | 409 EXPECT_LE(1, frames_captured()); |
380 } | 410 } |
381 | 411 |
382 // Test that we can copy twice from an accelerated composited page. | 412 // Test that we can copy twice from an accelerated composited page. |
383 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest, CopyTwice) { | 413 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest, CopyTwice) { |
384 SET_UP_SURFACE_OR_PASS_TEST(); | 414 SET_UP_SURFACE_OR_PASS_TEST(NULL); |
385 RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort(); | 415 RenderWidgetHostViewPort* const view = GetRenderWidgetHostViewPort(); |
386 if (!view->CanCopyToVideoFrame()) { | 416 if (!view->CanCopyToVideoFrame()) { |
387 LOG(WARNING) << ("Blindly passing this test: " | 417 LOG(WARNING) << ("Blindly passing this test: " |
388 "CopyFromCompositingSurfaceToVideoFrame() not supported " | 418 "CopyFromCompositingSurfaceToVideoFrame() not supported " |
389 "on this platform."); | 419 "on this platform."); |
390 return; | 420 return; |
391 } | 421 } |
392 | 422 |
393 base::RunLoop run_loop; | 423 base::RunLoop run_loop; |
394 scoped_refptr<media::VideoFrame> first_output = | 424 scoped_refptr<media::VideoFrame> first_output = |
(...skipping 16 matching lines...) Expand all Loading... |
411 base::Unretained(this), | 441 base::Unretained(this), |
412 base::MessageLoopProxy::current(), | 442 base::MessageLoopProxy::current(), |
413 run_loop.QuitClosure(), | 443 run_loop.QuitClosure(), |
414 base::Time::Now())); | 444 base::Time::Now())); |
415 run_loop.Run(); | 445 run_loop.Run(); |
416 | 446 |
417 EXPECT_EQ(2, callback_invoke_count()); | 447 EXPECT_EQ(2, callback_invoke_count()); |
418 EXPECT_EQ(2, frames_captured()); | 448 EXPECT_EQ(2, frames_captured()); |
419 } | 449 } |
420 | 450 |
| 451 class CompositingRenderWidgetHostViewBrowserTestTabCapture |
| 452 : public CompositingRenderWidgetHostViewBrowserTest { |
| 453 public: |
| 454 CompositingRenderWidgetHostViewBrowserTestTabCapture() |
| 455 : expected_copy_from_compositing_surface_result_(false), |
| 456 allowable_error_(0), |
| 457 test_url_("data:text/html,<!doctype html>") {} |
| 458 |
| 459 virtual void SetUp() OVERRIDE { |
| 460 ui::DisableTestCompositor(); |
| 461 CompositingRenderWidgetHostViewBrowserTest::SetUp(); |
| 462 } |
| 463 |
| 464 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
| 465 // TODO(Hubbe): This code is very similar to some code in |
| 466 // gpu_feature_browsertest.cc, and should really be shared in a common |
| 467 // location. |
| 468 if (!command_line->HasSwitch(switches::kUseGpuInTests)) { |
| 469 CHECK(!command_line->HasSwitch(switches::kUseGL)) |
| 470 << "kUseGL must not be set by test framework code!"; |
| 471 command_line->AppendSwitchASCII(switches::kUseGL, |
| 472 gfx::kGLImplementationOSMesaName); |
| 473 } |
| 474 } |
| 475 |
| 476 void CopyFromCompositingSurfaceCallback(base::Closure quit_callback, |
| 477 bool result, |
| 478 const SkBitmap& bitmap) { |
| 479 EXPECT_EQ(expected_copy_from_compositing_surface_result_, result); |
| 480 |
| 481 const SkBitmap& expected_bitmap = |
| 482 expected_copy_from_compositing_surface_bitmap_; |
| 483 EXPECT_EQ(expected_bitmap.width(), bitmap.width()); |
| 484 EXPECT_EQ(expected_bitmap.height(), bitmap.height()); |
| 485 EXPECT_EQ(expected_bitmap.config(), bitmap.config()); |
| 486 SkAutoLockPixels expected_bitmap_lock(expected_bitmap); |
| 487 SkAutoLockPixels bitmap_lock(bitmap); |
| 488 int fails = 0; |
| 489 for (int i = 0; i < bitmap.width() && fails < 10; ++i) { |
| 490 for (int j = 0; j < bitmap.height() && fails < 10; ++j) { |
| 491 SkColor expected_color = expected_bitmap.getColor(i, j); |
| 492 SkColor color = bitmap.getColor(i, j); |
| 493 EXPECT_NEAR(expected_color, color, allowable_error_) |
| 494 << "expected_color: " << std::hex << expected_color |
| 495 << " color: " << color |
| 496 << " Failed at " << std::dec << i << ", " << j |
| 497 << " Failure " << ++fails; |
| 498 } |
| 499 } |
| 500 EXPECT_LT(fails, 10); |
| 501 |
| 502 quit_callback.Run(); |
| 503 } |
| 504 |
| 505 void SetExpectedCopyFromCompositingSurfaceResult(bool result, |
| 506 const SkBitmap& bitmap) { |
| 507 expected_copy_from_compositing_surface_result_ = result; |
| 508 expected_copy_from_compositing_surface_bitmap_ = bitmap; |
| 509 } |
| 510 |
| 511 void SetAllowableError(int amount) { allowable_error_ = amount; } |
| 512 |
| 513 virtual GURL TestUrl() OVERRIDE { |
| 514 return GURL(test_url_); |
| 515 } |
| 516 |
| 517 void SetTestUrl(std::string url) { test_url_ = url; } |
| 518 |
| 519 private: |
| 520 bool expected_copy_from_compositing_surface_result_; |
| 521 SkBitmap expected_copy_from_compositing_surface_bitmap_; |
| 522 int allowable_error_; |
| 523 std::string test_url_; |
| 524 }; |
| 525 |
| 526 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture, |
| 527 CopyFromCompositingSurface_Origin_Unscaled) { |
| 528 SetTestUrl("data:text/html,<!doctype html>" |
| 529 "<div class='left'>" |
| 530 " <div class='right'></div>" |
| 531 "</div>" |
| 532 "<style>" |
| 533 "body { padding: 0; margin: 0; }" |
| 534 ".left { position: absolute;" |
| 535 " background: #0ff;" |
| 536 " width: 200px;" |
| 537 " height: 300px;" |
| 538 "}" |
| 539 ".right { position: absolute;" |
| 540 " left: 200px;" |
| 541 " background: #ff0;" |
| 542 " width: 200px;" |
| 543 " height: 300px;" |
| 544 "}" |
| 545 "</style>" |
| 546 "<script>" |
| 547 " domAutomationController.setAutomationId(0);" |
| 548 " domAutomationController.send(\"DONE\");" |
| 549 "</script>"); |
| 550 |
| 551 SET_UP_SURFACE_OR_PASS_TEST("\"DONE\""); |
| 552 |
| 553 RenderViewHost* const rwh = |
| 554 shell()->web_contents()->GetRenderViewHost(); |
| 555 RenderWidgetHostViewPort* rwhvp = |
| 556 static_cast<RenderWidgetHostViewPort*>(rwh->GetView()); |
| 557 |
| 558 // The page is loaded in the renderer, wait for a new frame to arrive. |
| 559 uint32 frame = rwhvp->RendererFrameNumber(); |
| 560 RenderWidgetHostImpl::From(rwh)->ScheduleComposite(); |
| 561 while (rwhvp->RendererFrameNumber() == frame) |
| 562 GiveItSomeTime(); |
| 563 |
| 564 gfx::Rect bounds = gfx::Rect(400, 300); |
| 565 EXPECT_LE(bounds.width(), rwhvp->GetViewBounds().width()); |
| 566 EXPECT_LE(bounds.height(), rwhvp->GetViewBounds().height()); |
| 567 |
| 568 gfx::Size out_size = bounds.size(); |
| 569 |
| 570 SkBitmap expected_bitmap; |
| 571 expected_bitmap.setConfig( |
| 572 SkBitmap::kARGB_8888_Config, out_size.width(), out_size.height()); |
| 573 expected_bitmap.allocPixels(); |
| 574 // Left half is #0ff. |
| 575 expected_bitmap.eraseARGB(255, 0, 255, 255); |
| 576 // Right half is #ff0. |
| 577 { |
| 578 SkAutoLockPixels lock(expected_bitmap); |
| 579 for (int i = 0; i < out_size.width() / 2; ++i) { |
| 580 for (int j = 0; j < out_size.height(); ++j) { |
| 581 *expected_bitmap.getAddr32(out_size.width() / 2 + i, j) = |
| 582 SkColorSetARGB(255, 255, 255, 0); |
| 583 } |
| 584 } |
| 585 } |
| 586 SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap); |
| 587 |
| 588 base::RunLoop run_loop; |
| 589 base::Callback<void(bool, const SkBitmap&)> callback = |
| 590 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture:: |
| 591 CopyFromCompositingSurfaceCallback, |
| 592 base::Unretained(this), |
| 593 run_loop.QuitClosure()); |
| 594 rwhvp->CopyFromCompositingSurface(bounds, out_size, callback); |
| 595 run_loop.Run(); |
| 596 } |
| 597 |
| 598 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture, |
| 599 CopyFromCompositingSurface_Origin_Scaled) { |
| 600 SetTestUrl("data:text/html,<!doctype html>" |
| 601 "<div class='left'>" |
| 602 " <div class='right'></div>" |
| 603 "</div>" |
| 604 "<style>" |
| 605 "body { padding: 0; margin: 0; }" |
| 606 ".left { position: absolute;" |
| 607 " background: #0ff;" |
| 608 " width: 200px;" |
| 609 " height: 300px;" |
| 610 "}" |
| 611 ".right { position: absolute;" |
| 612 " left: 200px;" |
| 613 " background: #ff0;" |
| 614 " width: 200px;" |
| 615 " height: 300px;" |
| 616 "}" |
| 617 "</style>" |
| 618 "<script>" |
| 619 " domAutomationController.setAutomationId(0);" |
| 620 " domAutomationController.send(\"DONE\");" |
| 621 "</script>"); |
| 622 |
| 623 SET_UP_SURFACE_OR_PASS_TEST("\"DONE\""); |
| 624 |
| 625 RenderViewHost* const rwh = |
| 626 shell()->web_contents()->GetRenderViewHost(); |
| 627 RenderWidgetHostViewPort* rwhvp = |
| 628 static_cast<RenderWidgetHostViewPort*>(rwh->GetView()); |
| 629 |
| 630 // The page is loaded in the renderer, wait for a new frame to arrive. |
| 631 uint32 frame = rwhvp->RendererFrameNumber(); |
| 632 RenderWidgetHostImpl::From(rwh)->ScheduleComposite(); |
| 633 while (rwhvp->RendererFrameNumber() == frame) |
| 634 GiveItSomeTime(); |
| 635 |
| 636 gfx::Rect bounds = gfx::Rect(400, 300); |
| 637 EXPECT_LE(bounds.width(), rwhvp->GetViewBounds().width()); |
| 638 EXPECT_LE(bounds.height(), rwhvp->GetViewBounds().height()); |
| 639 |
| 640 // Scale the output to 200x100. |
| 641 gfx::Size out_size(200, 100); |
| 642 |
| 643 SkBitmap expected_bitmap; |
| 644 expected_bitmap.setConfig( |
| 645 SkBitmap::kARGB_8888_Config, out_size.width(), out_size.height()); |
| 646 expected_bitmap.allocPixels(); |
| 647 // Left half is #0ff. |
| 648 expected_bitmap.eraseARGB(255, 0, 255, 255); |
| 649 // Right half is #ff0. |
| 650 { |
| 651 SkAutoLockPixels lock(expected_bitmap); |
| 652 for (int i = 0; i < out_size.width() / 2; ++i) { |
| 653 for (int j = 0; j < out_size.height(); ++j) { |
| 654 *expected_bitmap.getAddr32(out_size.width() / 2 + i, j) = |
| 655 SkColorSetARGB(255, 255, 255, 0); |
| 656 } |
| 657 } |
| 658 } |
| 659 SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap); |
| 660 |
| 661 base::RunLoop run_loop; |
| 662 base::Callback<void(bool, const SkBitmap&)> callback = |
| 663 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture:: |
| 664 CopyFromCompositingSurfaceCallback, |
| 665 base::Unretained(this), |
| 666 run_loop.QuitClosure()); |
| 667 rwhvp->CopyFromCompositingSurface(bounds, out_size, callback); |
| 668 run_loop.Run(); |
| 669 } |
| 670 |
| 671 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture, |
| 672 CopyFromCompositingSurface_Cropped_Unscaled) { |
| 673 SetTestUrl("data:text/html,<!doctype html>" |
| 674 "<div class='left'>" |
| 675 " <div class='right'></div>" |
| 676 "</div>" |
| 677 "<style>" |
| 678 "body { padding: 0; margin: 0; }" |
| 679 ".left { position: absolute;" |
| 680 " background: #0ff;" |
| 681 " width: 200px;" |
| 682 " height: 300px;" |
| 683 "}" |
| 684 ".right { position: absolute;" |
| 685 " left: 200px;" |
| 686 " background: #ff0;" |
| 687 " width: 200px;" |
| 688 " height: 300px;" |
| 689 "}" |
| 690 "</style>" |
| 691 "<script>" |
| 692 " domAutomationController.setAutomationId(0);" |
| 693 " domAutomationController.send(\"DONE\");" |
| 694 "</script>"); |
| 695 |
| 696 SET_UP_SURFACE_OR_PASS_TEST("\"DONE\""); |
| 697 |
| 698 RenderViewHost* const rwh = |
| 699 shell()->web_contents()->GetRenderViewHost(); |
| 700 RenderWidgetHostViewPort* rwhvp = |
| 701 static_cast<RenderWidgetHostViewPort*>(rwh->GetView()); |
| 702 |
| 703 // The page is loaded in the renderer, wait for a new frame to arrive. |
| 704 uint32 frame = rwhvp->RendererFrameNumber(); |
| 705 RenderWidgetHostImpl::From(rwh)->ScheduleComposite(); |
| 706 while (rwhvp->RendererFrameNumber() == frame) |
| 707 GiveItSomeTime(); |
| 708 |
| 709 gfx::Rect bounds = gfx::Rect(400, 300); |
| 710 EXPECT_LE(bounds.width(), rwhvp->GetViewBounds().width()); |
| 711 EXPECT_LE(bounds.height(), rwhvp->GetViewBounds().height()); |
| 712 |
| 713 // Grab 60x60 pixels from the center of the tab contents. |
| 714 bounds = gfx::Rect(bounds.CenterPoint() - gfx::Vector2d(30, 30), |
| 715 gfx::Size(60, 60)); |
| 716 gfx::Size out_size = bounds.size(); |
| 717 |
| 718 SkBitmap expected_bitmap; |
| 719 expected_bitmap.setConfig( |
| 720 SkBitmap::kARGB_8888_Config, out_size.width(), out_size.height()); |
| 721 expected_bitmap.allocPixels(); |
| 722 // Left half is #0ff. |
| 723 expected_bitmap.eraseARGB(255, 0, 255, 255); |
| 724 // Right half is #ff0. |
| 725 { |
| 726 SkAutoLockPixels lock(expected_bitmap); |
| 727 for (int i = 0; i < out_size.width() / 2; ++i) { |
| 728 for (int j = 0; j < out_size.height(); ++j) { |
| 729 *expected_bitmap.getAddr32(out_size.width() / 2 + i, j) = |
| 730 SkColorSetARGB(255, 255, 255, 0); |
| 731 } |
| 732 } |
| 733 } |
| 734 SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap); |
| 735 |
| 736 base::RunLoop run_loop; |
| 737 base::Callback<void(bool, const SkBitmap&)> callback = |
| 738 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture:: |
| 739 CopyFromCompositingSurfaceCallback, |
| 740 base::Unretained(this), |
| 741 run_loop.QuitClosure()); |
| 742 rwhvp->CopyFromCompositingSurface(bounds, out_size, callback); |
| 743 run_loop.Run(); |
| 744 } |
| 745 |
| 746 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture, |
| 747 CopyFromCompositingSurface_Cropped_Scaled) { |
| 748 SetTestUrl("data:text/html,<!doctype html>" |
| 749 "<div class='left'>" |
| 750 " <div class='right'></div>" |
| 751 "</div>" |
| 752 "<style>" |
| 753 "body { padding: 0; margin: 0; }" |
| 754 ".left { position: absolute;" |
| 755 " background: #0ff;" |
| 756 " width: 200px;" |
| 757 " height: 300px;" |
| 758 "}" |
| 759 ".right { position: absolute;" |
| 760 " left: 200px;" |
| 761 " background: #ff0;" |
| 762 " width: 200px;" |
| 763 " height: 300px;" |
| 764 "}" |
| 765 "</style>" |
| 766 "<script>" |
| 767 " domAutomationController.setAutomationId(0);" |
| 768 " domAutomationController.send(\"DONE\");" |
| 769 "</script>"); |
| 770 |
| 771 SET_UP_SURFACE_OR_PASS_TEST("\"DONE\""); |
| 772 |
| 773 RenderViewHost* const rwh = |
| 774 shell()->web_contents()->GetRenderViewHost(); |
| 775 RenderWidgetHostViewPort* rwhvp = |
| 776 static_cast<RenderWidgetHostViewPort*>(rwh->GetView()); |
| 777 |
| 778 // The page is loaded in the renderer, wait for a new frame to arrive. |
| 779 uint32 frame = rwhvp->RendererFrameNumber(); |
| 780 RenderWidgetHostImpl::From(rwh)->ScheduleComposite(); |
| 781 while (rwhvp->RendererFrameNumber() == frame) |
| 782 GiveItSomeTime(); |
| 783 |
| 784 gfx::Rect bounds = gfx::Rect(400, 300); |
| 785 EXPECT_LE(bounds.width(), rwhvp->GetViewBounds().width()); |
| 786 EXPECT_LE(bounds.height(), rwhvp->GetViewBounds().height()); |
| 787 |
| 788 // Grab 60x60 pixels from the center of the tab contents. |
| 789 bounds = gfx::Rect(bounds.CenterPoint() - gfx::Vector2d(30, 30), |
| 790 gfx::Size(60, 60)); |
| 791 |
| 792 // Scale to 20 x 10. |
| 793 gfx::Size out_size(20, 10); |
| 794 |
| 795 SkBitmap expected_bitmap; |
| 796 expected_bitmap.setConfig( |
| 797 SkBitmap::kARGB_8888_Config, out_size.width(), out_size.height()); |
| 798 expected_bitmap.allocPixels(); |
| 799 // Left half is #0ff. |
| 800 expected_bitmap.eraseARGB(255, 0, 255, 255); |
| 801 // Right half is #ff0. |
| 802 { |
| 803 SkAutoLockPixels lock(expected_bitmap); |
| 804 for (int i = 0; i < out_size.width() / 2; ++i) { |
| 805 for (int j = 0; j < out_size.height(); ++j) { |
| 806 *expected_bitmap.getAddr32(out_size.width() / 2 + i, j) = |
| 807 SkColorSetARGB(255, 255, 255, 0); |
| 808 } |
| 809 } |
| 810 } |
| 811 SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap); |
| 812 |
| 813 base::RunLoop run_loop; |
| 814 base::Callback<void(bool, const SkBitmap&)> callback = |
| 815 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture:: |
| 816 CopyFromCompositingSurfaceCallback, |
| 817 base::Unretained(this), |
| 818 run_loop.QuitClosure()); |
| 819 rwhvp->CopyFromCompositingSurface(bounds, out_size, callback); |
| 820 run_loop.Run(); |
| 821 } |
| 822 |
421 #endif // !defined(OS_ANDROID) && !defined(OS_IOS) | 823 #endif // !defined(OS_ANDROID) && !defined(OS_IOS) |
422 | 824 |
423 } // namespace | 825 } // namespace |
424 } // namespace content | 826 } // namespace content |
OLD | NEW |