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 |