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
3 // found in the LICENSE file.
5 #include "base/command_line.h"
6 #include "base/message_loop/message_loop_proxy.h"
7 #include "base/path_service.h"
8 #include "base/run_loop.h"
9 #include "content/browser/gpu/compositor_util.h"
10 #include "content/browser/gpu/gpu_data_manager_impl.h"
11 #include "content/browser/renderer_host/dip_util.h"
12 #include "content/browser/renderer_host/render_widget_host_impl.h"
13 #include "content/port/browser/render_widget_host_view_frame_subscriber.h"
14 #include "content/port/browser/render_widget_host_view_port.h"
15 #include "content/public/browser/gpu_data_manager.h"
16 #include "content/public/browser/render_view_host.h"
17 #include "content/public/browser/web_contents.h"
18 #include "content/public/common/content_paths.h"
19 #include "content/public/common/content_switches.h"
20 #include "content/public/common/url_constants.h"
21 #include "content/public/test/browser_test_utils.h"
22 #include "content/shell/browser/shell.h"
23 #include "content/test/content_browser_test.h"
24 #include "content/test/content_browser_test_utils.h"
25 #include "media/base/video_frame.h"
26 #include "media/filters/skcanvas_video_renderer.h"
27 #include "net/base/net_util.h"
28 #include "third_party/skia/include/core/SkBitmap.h"
29 #include "third_party/skia/include/core/SkBitmapDevice.h"
30 #include "third_party/skia/include/core/SkCanvas.h"
31 #include "ui/base/ui_base_switches.h"
32 #include "ui/gfx/size_conversions.h"
33 #include "ui/gfx/switches.h"
34 #include "ui/gl/gl_switches.h"
36 #if defined(OS_MACOSX)
37 #include "ui/gl/io_surface_support_mac.h"
41 #include "base/win/windows_version.h"
42 #include "ui/gfx/win/dpi.h"
48 // Convenience macro: Short-circuit a pass for the tests where platform support
49 // for forced-compositing mode (or disabled-compositing mode) is lacking.
50 #define SET_UP_SURFACE_OR_PASS_TEST(wait_message) \
51 if (!SetUpSourceSurface(wait_message)) { \
53 << ("Blindly passing this test: This platform does not support " \
54 "forced compositing (or forced-disabled compositing) mode."); \
58 // Convenience macro: Short-circuit a pass for platforms where setting up
60 #define PASS_TEST_IF_SCALE_FACTOR_NOT_SUPPORTED(factor) \
61 if (ui::GetImageScale( \
62 GetScaleFactorForView(GetRenderWidgetHostViewPort())) != factor) { \
63 LOG(WARNING) << "Blindly passing this test: failed to set up " \
64 "scale factor: " << factor; \
68 // Common base class for browser tests. This is subclassed twice: Once to test
69 // the browser in forced-compositing mode, and once to test with compositing
71 class RenderWidgetHostViewBrowserTest
: public ContentBrowserTest
{
73 RenderWidgetHostViewBrowserTest()
74 : frame_size_(400, 300),
75 callback_invoke_count_(0),
76 frames_captured_(0) {}
78 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE
{
79 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA
, &test_dir_
));
80 ContentBrowserTest::SetUpInProcessBrowserTestFixture();
83 // Attempts to set up the source surface. Returns false if unsupported on the
85 virtual bool SetUpSourceSurface(const char* wait_message
) = 0;
87 int callback_invoke_count() const {
88 return callback_invoke_count_
;
91 int frames_captured() const {
92 return frames_captured_
;
95 const gfx::Size
& frame_size() const {
99 const base::FilePath
& test_dir() const {
103 RenderViewHost
* GetRenderViewHost() const {
104 RenderViewHost
* const rvh
= shell()->web_contents()->GetRenderViewHost();
109 RenderWidgetHostImpl
* GetRenderWidgetHost() const {
110 RenderWidgetHostImpl
* const rwh
= RenderWidgetHostImpl::From(
111 shell()->web_contents()->GetRenderWidgetHostView()->
112 GetRenderWidgetHost());
117 RenderWidgetHostViewPort
* GetRenderWidgetHostViewPort() const {
118 RenderWidgetHostViewPort
* const view
=
119 RenderWidgetHostViewPort::FromRWHV(GetRenderViewHost()->GetView());
124 // Callback when using CopyFromBackingStore() API.
125 void FinishCopyFromBackingStore(const base::Closure
& quit_closure
,
127 const SkBitmap
& bitmap
) {
128 ++callback_invoke_count_
;
129 if (frame_captured
) {
131 EXPECT_FALSE(bitmap
.empty());
133 if (!quit_closure
.is_null())
137 // Callback when using CopyFromCompositingSurfaceToVideoFrame() API.
138 void FinishCopyFromCompositingSurface(const base::Closure
& quit_closure
,
139 bool frame_captured
) {
140 ++callback_invoke_count_
;
143 if (!quit_closure
.is_null())
147 // Callback when using frame subscriber API.
148 void FrameDelivered(const scoped_refptr
<base::MessageLoopProxy
>& loop
,
149 base::Closure quit_closure
,
150 base::TimeTicks timestamp
,
151 bool frame_captured
) {
152 ++callback_invoke_count_
;
155 if (!quit_closure
.is_null())
156 loop
->PostTask(FROM_HERE
, quit_closure
);
159 // Copy one frame using the CopyFromBackingStore API.
160 void RunBasicCopyFromBackingStoreTest() {
161 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
163 // Repeatedly call CopyFromBackingStore() since, on some platforms (e.g.,
164 // Windows), the operation will fail until the first "present" has been
166 int count_attempts
= 0;
169 base::RunLoop run_loop
;
170 GetRenderViewHost()->CopyFromBackingStore(
174 &RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore
,
175 base::Unretained(this),
176 run_loop
.QuitClosure()));
179 if (frames_captured())
185 EXPECT_EQ(count_attempts
, callback_invoke_count());
186 EXPECT_EQ(1, frames_captured());
190 // Waits until the source is available for copying.
191 void WaitForCopySourceReady() {
192 while (!GetRenderWidgetHostViewPort()->IsSurfaceAvailableForCopy())
196 // Run the current message loop for a short time without unwinding the current
198 static void GiveItSomeTime() {
199 base::RunLoop run_loop
;
200 base::MessageLoop::current()->PostDelayedTask(
202 run_loop
.QuitClosure(),
203 base::TimeDelta::FromMilliseconds(10));
208 const gfx::Size frame_size_
;
209 base::FilePath test_dir_
;
210 int callback_invoke_count_
;
211 int frames_captured_
;
214 enum CompositingMode
{
216 SOFTWARE_COMPOSITING
,
219 class CompositingRenderWidgetHostViewBrowserTest
220 : public RenderWidgetHostViewBrowserTest
,
221 public testing::WithParamInterface
<CompositingMode
> {
223 explicit CompositingRenderWidgetHostViewBrowserTest()
224 : compositing_mode_(GetParam()) {}
226 virtual void SetUp() OVERRIDE
{
227 if (compositing_mode_
== SOFTWARE_COMPOSITING
)
228 UseSoftwareCompositing();
229 RenderWidgetHostViewBrowserTest::SetUp();
232 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
233 // Note: Not appending kForceCompositingMode switch here, since not all bots
234 // support compositing. Some bots will run with compositing on, and others
235 // won't. Therefore, the call to SetUpSourceSurface() later on will detect
236 // whether compositing mode is actually on or not. If not, the tests will
237 // pass blindly, logging a warning message, since we cannot test what the
238 // platform/implementation does not support.
239 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line
);
242 virtual GURL
TestUrl() {
243 return net::FilePathToFileURL(
244 test_dir().AppendASCII("rwhv_compositing_animation.html"));
247 virtual bool SetUpSourceSurface(const char* wait_message
) OVERRIDE
{
248 if (!IsForceCompositingModeEnabled())
249 return false; // See comment in SetUpCommandLine().
250 #if defined(OS_MACOSX)
251 CHECK(IOSurfaceSupport::Initialize());
254 content::DOMMessageQueue message_queue
;
255 NavigateToURL(shell(), TestUrl());
256 if (wait_message
!= NULL
) {
257 std::string
result(wait_message
);
258 if (!message_queue
.WaitForMessage(&result
)) {
259 EXPECT_TRUE(false) << "WaitForMessage " << result
<< " failed.";
264 #if !defined(USE_AURA)
265 if (!GetRenderWidgetHost()->is_accelerated_compositing_active())
266 return false; // Renderer did not turn on accelerated compositing.
269 // Using accelerated compositing, but a compositing surface might not be
270 // available yet. So, wait for it.
271 WaitForCopySourceReady();
276 const CompositingMode compositing_mode_
;
278 DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewBrowserTest
);
281 class NonCompositingRenderWidgetHostViewBrowserTest
282 : public RenderWidgetHostViewBrowserTest
{
284 NonCompositingRenderWidgetHostViewBrowserTest() {}
286 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
287 // Note: Appending the kDisableAcceleratedCompositing switch here, but there
288 // are some builds that only use compositing and will ignore this switch.
289 // Therefore, the call to SetUpSourceSurface() later on will detect whether
290 // compositing mode is actually off. If it's on, the tests will pass
291 // blindly, logging a warning message, since we cannot test what the
292 // platform/implementation does not support.
293 command_line
->AppendSwitch(switches::kDisableAcceleratedCompositing
);
294 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line
);
297 virtual GURL
TestUrl() {
298 return GURL(kAboutBlankURL
);
301 virtual bool SetUpSourceSurface(const char* wait_message
) OVERRIDE
{
302 if (IsForceCompositingModeEnabled())
303 return false; // See comment in SetUpCommandLine().
305 content::DOMMessageQueue message_queue
;
306 NavigateToURL(shell(), TestUrl());
307 if (wait_message
!= NULL
) {
308 std::string
result(wait_message
);
309 if (!message_queue
.WaitForMessage(&result
)) {
310 EXPECT_TRUE(false) << "WaitForMessage " << result
<< " failed.";
315 WaitForCopySourceReady();
316 // Return whether the renderer left accelerated compositing turned off.
317 return !GetRenderWidgetHost()->is_accelerated_compositing_active();
321 DISALLOW_COPY_AND_ASSIGN(NonCompositingRenderWidgetHostViewBrowserTest
);
324 class FakeFrameSubscriber
: public RenderWidgetHostViewFrameSubscriber
{
327 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback
)
328 : callback_(callback
) {
331 virtual bool ShouldCaptureFrame(base::TimeTicks present_time
,
332 scoped_refptr
<media::VideoFrame
>* storage
,
333 DeliverFrameCallback
* callback
) OVERRIDE
{
334 // Only allow one frame capture to be made. Otherwise, the compositor could
335 // start multiple captures, unbounded, and eventually its own limiter logic
336 // will begin invoking |callback| with a |false| result. This flakes out
337 // the unit tests, since they receive a "failed" callback before the later
338 // "success" callbacks.
339 if (callback_
.is_null())
341 *storage
= media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
342 *callback
= callback_
;
348 DeliverFrameCallback callback_
;
351 // Disable tests for Android and IOS as these platforms have incomplete
353 #if !defined(OS_ANDROID) && !defined(OS_IOS)
355 // The CopyFromBackingStore() API should work on all platforms when compositing
357 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
,
358 CopyFromBackingStore
) {
359 RunBasicCopyFromBackingStoreTest();
362 // The CopyFromBackingStore() API should work on all platforms when compositing
364 IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest
,
365 CopyFromBackingStore
) {
366 RunBasicCopyFromBackingStoreTest();
369 // Tests that the callback passed to CopyFromBackingStore is always called,
370 // even when the RenderWidgetHost is deleting in the middle of an async copy.
371 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
,
372 CopyFromBackingStore_CallbackDespiteDelete
) {
373 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
375 base::RunLoop run_loop
;
376 GetRenderViewHost()->CopyFromBackingStore(
379 base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore
,
380 base::Unretained(this), run_loop
.QuitClosure()));
381 // Delete the surface before the callback is run.
382 GetRenderWidgetHostViewPort()->AcceleratedSurfaceRelease();
385 EXPECT_EQ(1, callback_invoke_count());
388 // Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is
389 // always called, even when the RenderWidgetHost is deleting in the middle of
392 // Test is flaky on Win. http://crbug.com/276783
393 #if defined(OS_WIN) || (defined(OS_CHROMEOS) && !defined(NDEBUG))
394 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
395 DISABLED_CopyFromCompositingSurface_CallbackDespiteDelete
397 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
398 CopyFromCompositingSurface_CallbackDespiteDelete
400 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
,
401 MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete
) {
402 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
403 RenderWidgetHostViewPort
* const view
= GetRenderWidgetHostViewPort();
404 if (!view
->CanCopyToVideoFrame()) {
406 ("Blindly passing this test: CopyFromCompositingSurfaceToVideoFrame() "
407 "not supported on this platform.");
411 base::RunLoop run_loop
;
412 scoped_refptr
<media::VideoFrame
> dest
=
413 media::VideoFrame::CreateBlackFrame(frame_size());
414 view
->CopyFromCompositingSurfaceToVideoFrame(
415 gfx::Rect(view
->GetViewBounds().size()), dest
, base::Bind(
416 &RenderWidgetHostViewBrowserTest::FinishCopyFromCompositingSurface
,
417 base::Unretained(this), run_loop
.QuitClosure()));
418 // Delete the surface before the callback is run.
419 view
->AcceleratedSurfaceRelease();
422 EXPECT_EQ(1, callback_invoke_count());
425 // With compositing turned off, no platforms should support the
426 // CopyFromCompositingSurfaceToVideoFrame() API.
427 IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest
,
428 CopyFromCompositingSurfaceToVideoFrameCallbackTest
) {
429 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
430 EXPECT_FALSE(GetRenderWidgetHostViewPort()->CanCopyToVideoFrame());
433 // Test basic frame subscription functionality. We subscribe, and then run
434 // until at least one DeliverFrameCallback has been invoked.
435 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
,
436 FrameSubscriberTest
) {
437 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
438 RenderWidgetHostViewPort
* const view
= GetRenderWidgetHostViewPort();
439 if (!view
->CanSubscribeFrame()) {
440 LOG(WARNING
) << ("Blindly passing this test: Frame subscription not "
441 "supported on this platform.");
445 base::RunLoop run_loop
;
446 scoped_ptr
<RenderWidgetHostViewFrameSubscriber
> subscriber(
447 new FakeFrameSubscriber(
448 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered
,
449 base::Unretained(this),
450 base::MessageLoopProxy::current(),
451 run_loop
.QuitClosure())));
452 view
->BeginFrameSubscription(subscriber
.Pass());
454 view
->EndFrameSubscription();
456 EXPECT_LE(1, callback_invoke_count());
457 EXPECT_LE(1, frames_captured());
460 // Test that we can copy twice from an accelerated composited page.
461 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
, CopyTwice
) {
462 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
463 RenderWidgetHostViewPort
* const view
= GetRenderWidgetHostViewPort();
464 if (!view
->CanCopyToVideoFrame()) {
465 LOG(WARNING
) << ("Blindly passing this test: "
466 "CopyFromCompositingSurfaceToVideoFrame() not supported "
467 "on this platform.");
471 base::RunLoop run_loop
;
472 scoped_refptr
<media::VideoFrame
> first_output
=
473 media::VideoFrame::CreateBlackFrame(frame_size());
474 ASSERT_TRUE(first_output
.get());
475 scoped_refptr
<media::VideoFrame
> second_output
=
476 media::VideoFrame::CreateBlackFrame(frame_size());
477 ASSERT_TRUE(second_output
.get());
478 view
->CopyFromCompositingSurfaceToVideoFrame(
479 gfx::Rect(view
->GetViewBounds().size()),
481 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered
,
482 base::Unretained(this),
483 base::MessageLoopProxy::current(),
485 base::TimeTicks::Now()));
486 view
->CopyFromCompositingSurfaceToVideoFrame(
487 gfx::Rect(view
->GetViewBounds().size()),
489 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered
,
490 base::Unretained(this),
491 base::MessageLoopProxy::current(),
492 run_loop
.QuitClosure(),
493 base::TimeTicks::Now()));
496 EXPECT_EQ(2, callback_invoke_count());
497 EXPECT_EQ(2, frames_captured());
500 class CompositingRenderWidgetHostViewBrowserTestTabCapture
501 : public CompositingRenderWidgetHostViewBrowserTest
{
503 CompositingRenderWidgetHostViewBrowserTestTabCapture()
504 : expected_copy_from_compositing_surface_result_(false),
506 test_url_("data:text/html,<!doctype html>") {}
508 virtual void SetUp() OVERRIDE
{
510 CompositingRenderWidgetHostViewBrowserTest::SetUp();
513 void CopyFromCompositingSurfaceCallback(base::Closure quit_callback
,
515 const SkBitmap
& bitmap
) {
516 EXPECT_EQ(expected_copy_from_compositing_surface_result_
, result
);
522 const SkBitmap
& expected_bitmap
=
523 expected_copy_from_compositing_surface_bitmap_
;
524 EXPECT_EQ(expected_bitmap
.width(), bitmap
.width());
525 EXPECT_EQ(expected_bitmap
.height(), bitmap
.height());
526 EXPECT_EQ(expected_bitmap
.config(), bitmap
.config());
527 SkAutoLockPixels
expected_bitmap_lock(expected_bitmap
);
528 SkAutoLockPixels
bitmap_lock(bitmap
);
530 for (int i
= 0; i
< bitmap
.width() && fails
< 10; ++i
) {
531 for (int j
= 0; j
< bitmap
.height() && fails
< 10; ++j
) {
532 if (!exclude_rect_
.IsEmpty() && exclude_rect_
.Contains(i
, j
))
535 SkColor expected_color
= expected_bitmap
.getColor(i
, j
);
536 SkColor color
= bitmap
.getColor(i
, j
);
537 int expected_alpha
= SkColorGetA(expected_color
);
538 int alpha
= SkColorGetA(color
);
539 int expected_red
= SkColorGetR(expected_color
);
540 int red
= SkColorGetR(color
);
541 int expected_green
= SkColorGetG(expected_color
);
542 int green
= SkColorGetG(color
);
543 int expected_blue
= SkColorGetB(expected_color
);
544 int blue
= SkColorGetB(color
);
545 EXPECT_NEAR(expected_alpha
, alpha
, allowable_error_
)
546 << "expected_color: " << std::hex
<< expected_color
547 << " color: " << color
548 << " Failed at " << std::dec
<< i
<< ", " << j
549 << " Failure " << ++fails
;
550 EXPECT_NEAR(expected_red
, red
, allowable_error_
)
551 << "expected_color: " << std::hex
<< expected_color
552 << " color: " << color
553 << " Failed at " << std::dec
<< i
<< ", " << j
554 << " Failure " << ++fails
;
555 EXPECT_NEAR(expected_green
, green
, allowable_error_
)
556 << "expected_color: " << std::hex
<< expected_color
557 << " color: " << color
558 << " Failed at " << std::dec
<< i
<< ", " << j
559 << " Failure " << ++fails
;
560 EXPECT_NEAR(expected_blue
, blue
, allowable_error_
)
561 << "expected_color: " << std::hex
<< expected_color
562 << " color: " << color
563 << " Failed at " << std::dec
<< i
<< ", " << j
564 << " Failure " << ++fails
;
567 EXPECT_LT(fails
, 10);
572 void CopyFromCompositingSurfaceCallbackForVideo(
573 scoped_refptr
<media::VideoFrame
> video_frame
,
574 base::Closure quit_callback
,
576 EXPECT_EQ(expected_copy_from_compositing_surface_result_
, result
);
582 media::SkCanvasVideoRenderer video_renderer
;
585 bitmap
.setConfig(SkBitmap::kARGB_8888_Config
,
586 video_frame
->visible_rect().width(),
587 video_frame
->visible_rect().height(),
588 0, kOpaque_SkAlphaType
);
589 bitmap
.allocPixels();
591 SkBitmapDevice
device(bitmap
);
592 SkCanvas
canvas(&device
);
594 video_renderer
.Paint(video_frame
.get(),
596 video_frame
->visible_rect(),
599 CopyFromCompositingSurfaceCallback(quit_callback
,
604 void SetExpectedCopyFromCompositingSurfaceResult(bool result
,
605 const SkBitmap
& bitmap
) {
606 expected_copy_from_compositing_surface_result_
= result
;
607 expected_copy_from_compositing_surface_bitmap_
= bitmap
;
610 void SetAllowableError(int amount
) { allowable_error_
= amount
; }
611 void SetExcludeRect(gfx::Rect exclude
) { exclude_rect_
= exclude
; }
613 virtual GURL
TestUrl() OVERRIDE
{
614 return GURL(test_url_
);
617 void SetTestUrl(std::string url
) { test_url_
= url
; }
619 // Loads a page two boxes side-by-side, each half the width of
620 // |html_rect_size|, and with different background colors. The test then
621 // copies from |copy_rect| region of the page into a bitmap of size
622 // |output_size|, and compares that with a bitmap of size
623 // |expected_bitmap_size|.
624 // Note that |output_size| may not have the same size as |copy_rect| (e.g.
625 // when the output is scaled). Also note that |expected_bitmap_size| may not
626 // be the same as |output_size| (e.g. when the device scale factor is not 1).
627 void PerformTestWithLeftRightRects(const gfx::Size
& html_rect_size
,
628 const gfx::Rect
& copy_rect
,
629 const gfx::Size
& output_size
,
630 const gfx::Size
& expected_bitmap_size
,
632 const gfx::Size
box_size(html_rect_size
.width() / 2,
633 html_rect_size
.height());
634 SetTestUrl(base::StringPrintf(
635 "data:text/html,<!doctype html>"
637 " <div class='right'></div>"
640 "body { padding: 0; margin: 0; }"
641 ".left { position: absolute;"
646 ".right { position: absolute;"
654 " domAutomationController.setAutomationId(0);"
655 " domAutomationController.send(\"DONE\");"
663 SET_UP_SURFACE_OR_PASS_TEST("\"DONE\"");
664 if (!ShouldContinueAfterTestURLLoad())
667 RenderWidgetHostViewPort
* rwhvp
= GetRenderWidgetHostViewPort();
668 if (video_frame
&& !rwhvp
->CanCopyToVideoFrame()) {
669 // This should only happen on Mac when using the software compositor.
670 // Otherwise, raise an error. This can be removed when Mac is moved to a
671 // browser compositor.
672 // http://crbug.com/314190
673 #if defined(OS_MACOSX)
674 if (!content::GpuDataManager::GetInstance()->GpuAccessAllowed(NULL
)) {
675 LOG(WARNING
) << ("Blindly passing this test because copying to "
676 "video frames is not supported on this platform.");
683 // The page is loaded in the renderer, wait for a new frame to arrive.
684 uint32 frame
= rwhvp
->RendererFrameNumber();
685 while (!GetRenderWidgetHost()->ScheduleComposite())
687 while (rwhvp
->RendererFrameNumber() == frame
)
690 SkBitmap expected_bitmap
;
691 SetupLeftRightBitmap(expected_bitmap_size
, &expected_bitmap
);
692 SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap
);
694 base::RunLoop run_loop
;
696 // Allow pixel differences as long as we have the right idea.
697 SetAllowableError(0x10);
698 // Exclude the middle two columns which are blended between the two sides.
700 gfx::Rect(output_size
.width() / 2 - 1, 0, 2, output_size
.height()));
702 scoped_refptr
<media::VideoFrame
> video_frame
=
703 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
,
704 expected_bitmap_size
,
705 gfx::Rect(expected_bitmap_size
),
706 expected_bitmap_size
,
709 base::Callback
<void(bool success
)> callback
=
710 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
711 CopyFromCompositingSurfaceCallbackForVideo
,
712 base::Unretained(this),
714 run_loop
.QuitClosure());
715 rwhvp
->CopyFromCompositingSurfaceToVideoFrame(copy_rect
,
719 #if defined(USE_AURA)
720 if (!content::GpuDataManager::GetInstance()
721 ->CanUseGpuBrowserCompositor()) {
722 // Skia rendering can cause color differences, particularly in the
723 // middle two columns.
724 SetAllowableError(2);
726 gfx::Rect(output_size
.width() / 2 - 1, 0, 2, output_size
.height()));
730 base::Callback
<void(bool, const SkBitmap
&)> callback
=
731 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
732 CopyFromCompositingSurfaceCallback
,
733 base::Unretained(this),
734 run_loop
.QuitClosure());
735 rwhvp
->CopyFromCompositingSurface(copy_rect
,
738 SkBitmap::kARGB_8888_Config
);
743 // Sets up |bitmap| to have size |copy_size|. It floods the left half with
744 // #0ff and the right half with #ff0.
745 void SetupLeftRightBitmap(const gfx::Size
& copy_size
, SkBitmap
* bitmap
) {
747 SkBitmap::kARGB_8888_Config
, copy_size
.width(), copy_size
.height());
748 bitmap
->allocPixels();
749 // Left half is #0ff.
750 bitmap
->eraseARGB(255, 0, 255, 255);
751 // Right half is #ff0.
753 SkAutoLockPixels
lock(*bitmap
);
754 for (int i
= 0; i
< copy_size
.width() / 2; ++i
) {
755 for (int j
= 0; j
< copy_size
.height(); ++j
) {
756 *(bitmap
->getAddr32(copy_size
.width() / 2 + i
, j
)) =
757 SkColorSetARGB(255, 255, 255, 0);
764 virtual bool ShouldContinueAfterTestURLLoad() {
769 bool expected_copy_from_compositing_surface_result_
;
770 SkBitmap expected_copy_from_compositing_surface_bitmap_
;
771 int allowable_error_
;
772 gfx::Rect exclude_rect_
;
773 std::string test_url_
;
776 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
777 CopyFromCompositingSurface_Origin_Unscaled
) {
778 gfx::Rect
copy_rect(400, 300);
779 gfx::Size output_size
= copy_rect
.size();
780 gfx::Size expected_bitmap_size
= output_size
;
781 gfx::Size
html_rect_size(400, 300);
782 bool video_frame
= false;
783 PerformTestWithLeftRightRects(html_rect_size
,
786 expected_bitmap_size
,
790 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
791 CopyFromCompositingSurface_Origin_Scaled
) {
792 gfx::Rect
copy_rect(400, 300);
793 gfx::Size
output_size(200, 100);
794 gfx::Size expected_bitmap_size
= output_size
;
795 gfx::Size
html_rect_size(400, 300);
796 bool video_frame
= false;
797 PerformTestWithLeftRightRects(html_rect_size
,
800 expected_bitmap_size
,
804 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
805 CopyFromCompositingSurface_Cropped_Unscaled
) {
806 // Grab 60x60 pixels from the center of the tab contents.
807 gfx::Rect
copy_rect(400, 300);
808 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(30, 30),
810 gfx::Size output_size
= copy_rect
.size();
811 gfx::Size expected_bitmap_size
= output_size
;
812 gfx::Size
html_rect_size(400, 300);
813 bool video_frame
= false;
814 PerformTestWithLeftRightRects(html_rect_size
,
817 expected_bitmap_size
,
821 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
822 CopyFromCompositingSurface_Cropped_Scaled
) {
823 // Grab 60x60 pixels from the center of the tab contents.
824 gfx::Rect
copy_rect(400, 300);
825 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(30, 30),
827 gfx::Size
output_size(20, 10);
828 gfx::Size expected_bitmap_size
= output_size
;
829 gfx::Size
html_rect_size(400, 300);
830 bool video_frame
= false;
831 PerformTestWithLeftRightRects(html_rect_size
,
834 expected_bitmap_size
,
838 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
839 CopyFromCompositingSurface_ForVideoFrame
) {
840 // Grab 90x60 pixels from the center of the tab contents.
841 gfx::Rect
copy_rect(400, 300);
842 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(45, 30),
844 gfx::Size output_size
= copy_rect
.size();
845 gfx::Size expected_bitmap_size
= output_size
;
846 gfx::Size
html_rect_size(400, 300);
847 bool video_frame
= true;
848 PerformTestWithLeftRightRects(html_rect_size
,
851 expected_bitmap_size
,
855 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
856 CopyFromCompositingSurface_ForVideoFrame_Scaled
) {
857 // Grab 90x60 pixels from the center of the tab contents.
858 gfx::Rect
copy_rect(400, 300);
859 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(45, 30),
861 // Scale to 30 x 20 (preserve aspect ratio).
862 gfx::Size
output_size(30, 20);
863 gfx::Size expected_bitmap_size
= output_size
;
864 gfx::Size
html_rect_size(400, 300);
865 bool video_frame
= true;
866 PerformTestWithLeftRightRects(html_rect_size
,
869 expected_bitmap_size
,
873 class CompositingRenderWidgetHostViewTabCaptureHighDPI
874 : public CompositingRenderWidgetHostViewBrowserTestTabCapture
{
876 CompositingRenderWidgetHostViewTabCaptureHighDPI() : kScale(2.f
) {}
878 virtual void SetUpCommandLine(CommandLine
* cmd
) OVERRIDE
{
879 CompositingRenderWidgetHostViewBrowserTestTabCapture::SetUpCommandLine(cmd
);
880 cmd
->AppendSwitchASCII(switches::kForceDeviceScaleFactor
,
881 base::StringPrintf("%f", scale()));
883 cmd
->AppendSwitchASCII(switches::kHighDPISupport
, "1");
884 gfx::EnableHighDPISupport();
888 float scale() const { return kScale
; }
891 virtual bool ShouldContinueAfterTestURLLoad() OVERRIDE
{
892 PASS_TEST_IF_SCALE_FACTOR_NOT_SUPPORTED(scale());
898 DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewTabCaptureHighDPI
);
901 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewTabCaptureHighDPI
,
902 CopyFromCompositingSurface
) {
903 gfx::Rect
copy_rect(200, 150);
904 gfx::Size output_size
= copy_rect
.size();
905 gfx::Size expected_bitmap_size
=
906 gfx::ToFlooredSize(gfx::ScaleSize(output_size
, scale(), scale()));
907 gfx::Size
html_rect_size(200, 150);
908 bool video_frame
= false;
909 PerformTestWithLeftRightRects(html_rect_size
,
912 expected_bitmap_size
,
916 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewTabCaptureHighDPI
,
917 CopyFromCompositingSurfaceVideoFrame
) {
918 gfx::Size
html_rect_size(200, 150);
919 // Grab 90x60 pixels from the center of the tab contents.
920 gfx::Rect copy_rect
=
921 gfx::Rect(gfx::Rect(html_rect_size
).CenterPoint() - gfx::Vector2d(45, 30),
923 gfx::Size output_size
= copy_rect
.size();
924 gfx::Size expected_bitmap_size
=
925 gfx::ToFlooredSize(gfx::ScaleSize(output_size
, scale(), scale()));
926 bool video_frame
= true;
927 PerformTestWithLeftRightRects(html_rect_size
,
930 expected_bitmap_size
,
934 #if !defined(USE_AURA) && !defined(OS_MACOSX)
935 // TODO(danakj): Remove this case when GTK linux is no more and move the
936 // values inline to testing::Values() below.
937 static const CompositingMode kAllCompositingModes
[] = {GL_COMPOSITING
};
939 static const CompositingMode kAllCompositingModes
[] = {GL_COMPOSITING
,
940 SOFTWARE_COMPOSITING
};
943 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing
,
944 CompositingRenderWidgetHostViewBrowserTest
,
945 testing::ValuesIn(kAllCompositingModes
));
946 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing
,
947 CompositingRenderWidgetHostViewBrowserTestTabCapture
,
948 testing::ValuesIn(kAllCompositingModes
));
949 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing
,
950 CompositingRenderWidgetHostViewTabCaptureHighDPI
,
951 testing::ValuesIn(kAllCompositingModes
));
953 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
956 } // namespace content