Chromium Code Reviews| 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(); | |
|
piman
2013/07/02 01:49:09
So, ScheduleComposite early-outs if we're not in c
danakj
2013/07/03 01:08:45
I think that's okay. We already waited until we re
| |
| 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 |