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/public/test/content_browser_test.h"
23 #include "content/public/test/content_browser_test_utils.h"
24 #include "content/shell/browser/shell.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/SkCanvas.h"
30 #include "ui/base/ui_base_switches.h"
31 #include "ui/gfx/size_conversions.h"
32 #include "ui/gfx/switches.h"
33 #include "ui/gl/gl_switches.h"
35 #if defined(OS_MACOSX)
36 #include "ui/gl/io_surface_support_mac.h"
40 #include "base/win/windows_version.h"
41 #include "ui/gfx/win/dpi.h"
47 // Convenience macro: Short-circuit a pass for the tests where platform support
48 // for forced-compositing mode (or disabled-compositing mode) is lacking.
49 #define SET_UP_SURFACE_OR_PASS_TEST(wait_message) \
50 if (!SetUpSourceSurface(wait_message)) { \
52 << ("Blindly passing this test: This platform does not support " \
53 "forced compositing (or forced-disabled compositing) mode."); \
57 // Convenience macro: Short-circuit a pass for platforms where setting up
59 #define PASS_TEST_IF_SCALE_FACTOR_NOT_SUPPORTED(factor) \
60 if (ui::GetScaleForScaleFactor( \
61 GetScaleFactorForView(GetRenderWidgetHostViewPort())) != factor) { \
62 LOG(WARNING) << "Blindly passing this test: failed to set up " \
63 "scale factor: " << factor; \
67 // Common base class for browser tests. This is subclassed twice: Once to test
68 // the browser in forced-compositing mode, and once to test with compositing
70 class RenderWidgetHostViewBrowserTest
: public ContentBrowserTest
{
72 RenderWidgetHostViewBrowserTest()
73 : frame_size_(400, 300),
74 callback_invoke_count_(0),
75 frames_captured_(0) {}
77 virtual void SetUpOnMainThread() OVERRIDE
{
78 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA
, &test_dir_
));
81 // Attempts to set up the source surface. Returns false if unsupported on the
83 virtual bool SetUpSourceSurface(const char* wait_message
) = 0;
85 int callback_invoke_count() const {
86 return callback_invoke_count_
;
89 int frames_captured() const {
90 return frames_captured_
;
93 const gfx::Size
& frame_size() const {
97 const base::FilePath
& test_dir() const {
101 RenderViewHost
* GetRenderViewHost() const {
102 RenderViewHost
* const rvh
= shell()->web_contents()->GetRenderViewHost();
107 RenderWidgetHostImpl
* GetRenderWidgetHost() const {
108 RenderWidgetHostImpl
* const rwh
= RenderWidgetHostImpl::From(
109 shell()->web_contents()->GetRenderWidgetHostView()->
110 GetRenderWidgetHost());
115 RenderWidgetHostViewPort
* GetRenderWidgetHostViewPort() const {
116 RenderWidgetHostViewPort
* const view
=
117 RenderWidgetHostViewPort::FromRWHV(GetRenderViewHost()->GetView());
122 // Callback when using CopyFromBackingStore() API.
123 void FinishCopyFromBackingStore(const base::Closure
& quit_closure
,
125 const SkBitmap
& bitmap
) {
126 ++callback_invoke_count_
;
127 if (frame_captured
) {
129 EXPECT_FALSE(bitmap
.empty());
131 if (!quit_closure
.is_null())
135 // Callback when using CopyFromCompositingSurfaceToVideoFrame() API.
136 void FinishCopyFromCompositingSurface(const base::Closure
& quit_closure
,
137 bool frame_captured
) {
138 ++callback_invoke_count_
;
141 if (!quit_closure
.is_null())
145 // Callback when using frame subscriber API.
146 void FrameDelivered(const scoped_refptr
<base::MessageLoopProxy
>& loop
,
147 base::Closure quit_closure
,
148 base::TimeTicks timestamp
,
149 bool frame_captured
) {
150 ++callback_invoke_count_
;
153 if (!quit_closure
.is_null())
154 loop
->PostTask(FROM_HERE
, quit_closure
);
157 // Copy one frame using the CopyFromBackingStore API.
158 void RunBasicCopyFromBackingStoreTest() {
159 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
161 // Repeatedly call CopyFromBackingStore() since, on some platforms (e.g.,
162 // Windows), the operation will fail until the first "present" has been
164 int count_attempts
= 0;
167 base::RunLoop run_loop
;
168 GetRenderViewHost()->CopyFromBackingStore(
172 &RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore
,
173 base::Unretained(this),
174 run_loop
.QuitClosure()),
175 SkBitmap::kARGB_8888_Config
);
178 if (frames_captured())
184 EXPECT_EQ(count_attempts
, callback_invoke_count());
185 EXPECT_EQ(1, frames_captured());
189 // Waits until the source is available for copying.
190 void WaitForCopySourceReady() {
191 while (!GetRenderWidgetHostViewPort()->IsSurfaceAvailableForCopy())
195 // Run the current message loop for a short time without unwinding the current
197 static void GiveItSomeTime() {
198 base::RunLoop run_loop
;
199 base::MessageLoop::current()->PostDelayedTask(
201 run_loop
.QuitClosure(),
202 base::TimeDelta::FromMilliseconds(10));
207 const gfx::Size frame_size_
;
208 base::FilePath test_dir_
;
209 int callback_invoke_count_
;
210 int frames_captured_
;
213 enum CompositingMode
{
215 SOFTWARE_COMPOSITING
,
218 class CompositingRenderWidgetHostViewBrowserTest
219 : public RenderWidgetHostViewBrowserTest
,
220 public testing::WithParamInterface
<CompositingMode
> {
222 explicit CompositingRenderWidgetHostViewBrowserTest()
223 : compositing_mode_(GetParam()) {}
225 virtual void SetUp() OVERRIDE
{
226 if (compositing_mode_
== SOFTWARE_COMPOSITING
)
227 UseSoftwareCompositing();
228 RenderWidgetHostViewBrowserTest::SetUp();
231 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
232 // Note: Not appending kForceCompositingMode switch here, since not all bots
233 // support compositing. Some bots will run with compositing on, and others
234 // won't. Therefore, the call to SetUpSourceSurface() later on will detect
235 // whether compositing mode is actually on or not. If not, the tests will
236 // pass blindly, logging a warning message, since we cannot test what the
237 // platform/implementation does not support.
238 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line
);
241 virtual GURL
TestUrl() {
242 return net::FilePathToFileURL(
243 test_dir().AppendASCII("rwhv_compositing_animation.html"));
246 virtual bool SetUpSourceSurface(const char* wait_message
) OVERRIDE
{
247 if (!IsForceCompositingModeEnabled())
248 return false; // See comment in SetUpCommandLine().
249 #if defined(OS_MACOSX)
250 CHECK(IOSurfaceSupport::Initialize());
253 content::DOMMessageQueue message_queue
;
254 NavigateToURL(shell(), TestUrl());
255 if (wait_message
!= NULL
) {
256 std::string
result(wait_message
);
257 if (!message_queue
.WaitForMessage(&result
)) {
258 EXPECT_TRUE(false) << "WaitForMessage " << result
<< " failed.";
263 #if !defined(USE_AURA)
264 if (!GetRenderWidgetHost()->is_accelerated_compositing_active())
265 return false; // Renderer did not turn on accelerated compositing.
268 // Using accelerated compositing, but a compositing surface might not be
269 // available yet. So, wait for it.
270 WaitForCopySourceReady();
275 const CompositingMode compositing_mode_
;
277 DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewBrowserTest
);
280 class NonCompositingRenderWidgetHostViewBrowserTest
281 : public RenderWidgetHostViewBrowserTest
{
283 NonCompositingRenderWidgetHostViewBrowserTest() {}
285 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
286 // Note: Appending the kDisableAcceleratedCompositing switch here, but there
287 // are some builds that only use compositing and will ignore this switch.
288 // Therefore, the call to SetUpSourceSurface() later on will detect whether
289 // compositing mode is actually off. If it's on, the tests will pass
290 // blindly, logging a warning message, since we cannot test what the
291 // platform/implementation does not support.
292 command_line
->AppendSwitch(switches::kDisableAcceleratedCompositing
);
293 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line
);
296 virtual GURL
TestUrl() {
297 return GURL(kAboutBlankURL
);
300 virtual bool SetUpSourceSurface(const char* wait_message
) OVERRIDE
{
301 if (IsForceCompositingModeEnabled())
302 return false; // See comment in SetUpCommandLine().
304 content::DOMMessageQueue message_queue
;
305 NavigateToURL(shell(), TestUrl());
306 if (wait_message
!= NULL
) {
307 std::string
result(wait_message
);
308 if (!message_queue
.WaitForMessage(&result
)) {
309 EXPECT_TRUE(false) << "WaitForMessage " << result
<< " failed.";
314 WaitForCopySourceReady();
315 // Return whether the renderer left accelerated compositing turned off.
316 return !GetRenderWidgetHost()->is_accelerated_compositing_active();
320 DISALLOW_COPY_AND_ASSIGN(NonCompositingRenderWidgetHostViewBrowserTest
);
323 class FakeFrameSubscriber
: public RenderWidgetHostViewFrameSubscriber
{
326 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback
)
327 : callback_(callback
) {
330 virtual bool ShouldCaptureFrame(base::TimeTicks present_time
,
331 scoped_refptr
<media::VideoFrame
>* storage
,
332 DeliverFrameCallback
* callback
) OVERRIDE
{
333 // Only allow one frame capture to be made. Otherwise, the compositor could
334 // start multiple captures, unbounded, and eventually its own limiter logic
335 // will begin invoking |callback| with a |false| result. This flakes out
336 // the unit tests, since they receive a "failed" callback before the later
337 // "success" callbacks.
338 if (callback_
.is_null())
340 *storage
= media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
341 *callback
= callback_
;
347 DeliverFrameCallback callback_
;
350 // Disable tests for Android and IOS as these platforms have incomplete
352 #if !defined(OS_ANDROID) && !defined(OS_IOS)
354 // The CopyFromBackingStore() API should work on all platforms when compositing
356 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
,
357 CopyFromBackingStore
) {
358 RunBasicCopyFromBackingStoreTest();
361 // The CopyFromBackingStore() API should work on all platforms when compositing
363 IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest
,
364 CopyFromBackingStore
) {
365 RunBasicCopyFromBackingStoreTest();
368 // Tests that the callback passed to CopyFromBackingStore is always called,
369 // even when the RenderWidgetHost is deleting in the middle of an async copy.
370 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
,
371 CopyFromBackingStore_CallbackDespiteDelete
) {
372 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
374 base::RunLoop run_loop
;
375 GetRenderViewHost()->CopyFromBackingStore(
378 base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore
,
379 base::Unretained(this),
380 run_loop
.QuitClosure()),
381 SkBitmap::kARGB_8888_Config
);
382 // Delete the surface before the callback is run.
383 GetRenderWidgetHostViewPort()->AcceleratedSurfaceRelease();
386 EXPECT_EQ(1, callback_invoke_count());
389 // Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is
390 // always called, even when the RenderWidgetHost is deleting in the middle of
393 // Test is flaky on Win. http://crbug.com/276783
394 #if defined(OS_WIN) || (defined(OS_CHROMEOS) && !defined(NDEBUG))
395 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
396 DISABLED_CopyFromCompositingSurface_CallbackDespiteDelete
398 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
399 CopyFromCompositingSurface_CallbackDespiteDelete
401 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
,
402 MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete
) {
403 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
404 RenderWidgetHostViewPort
* const view
= GetRenderWidgetHostViewPort();
405 if (!view
->CanCopyToVideoFrame()) {
407 ("Blindly passing this test: CopyFromCompositingSurfaceToVideoFrame() "
408 "not supported on this platform.");
412 base::RunLoop run_loop
;
413 scoped_refptr
<media::VideoFrame
> dest
=
414 media::VideoFrame::CreateBlackFrame(frame_size());
415 view
->CopyFromCompositingSurfaceToVideoFrame(
416 gfx::Rect(view
->GetViewBounds().size()), dest
, base::Bind(
417 &RenderWidgetHostViewBrowserTest::FinishCopyFromCompositingSurface
,
418 base::Unretained(this), run_loop
.QuitClosure()));
419 // Delete the surface before the callback is run.
420 view
->AcceleratedSurfaceRelease();
423 EXPECT_EQ(1, callback_invoke_count());
426 // With compositing turned off, no platforms should support the
427 // CopyFromCompositingSurfaceToVideoFrame() API.
428 IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest
,
429 CopyFromCompositingSurfaceToVideoFrameCallbackTest
) {
430 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
431 EXPECT_FALSE(GetRenderWidgetHostViewPort()->CanCopyToVideoFrame());
434 // Test basic frame subscription functionality. We subscribe, and then run
435 // until at least one DeliverFrameCallback has been invoked.
436 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
,
437 FrameSubscriberTest
) {
438 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
439 RenderWidgetHostViewPort
* const view
= GetRenderWidgetHostViewPort();
440 if (!view
->CanSubscribeFrame()) {
441 LOG(WARNING
) << ("Blindly passing this test: Frame subscription not "
442 "supported on this platform.");
446 base::RunLoop run_loop
;
447 scoped_ptr
<RenderWidgetHostViewFrameSubscriber
> subscriber(
448 new FakeFrameSubscriber(
449 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered
,
450 base::Unretained(this),
451 base::MessageLoopProxy::current(),
452 run_loop
.QuitClosure())));
453 view
->BeginFrameSubscription(subscriber
.Pass());
455 view
->EndFrameSubscription();
457 EXPECT_LE(1, callback_invoke_count());
458 EXPECT_LE(1, frames_captured());
461 // Test that we can copy twice from an accelerated composited page.
462 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
, CopyTwice
) {
463 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
464 RenderWidgetHostViewPort
* const view
= GetRenderWidgetHostViewPort();
465 if (!view
->CanCopyToVideoFrame()) {
466 LOG(WARNING
) << ("Blindly passing this test: "
467 "CopyFromCompositingSurfaceToVideoFrame() not supported "
468 "on this platform.");
472 base::RunLoop run_loop
;
473 scoped_refptr
<media::VideoFrame
> first_output
=
474 media::VideoFrame::CreateBlackFrame(frame_size());
475 ASSERT_TRUE(first_output
.get());
476 scoped_refptr
<media::VideoFrame
> second_output
=
477 media::VideoFrame::CreateBlackFrame(frame_size());
478 ASSERT_TRUE(second_output
.get());
479 view
->CopyFromCompositingSurfaceToVideoFrame(
480 gfx::Rect(view
->GetViewBounds().size()),
482 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered
,
483 base::Unretained(this),
484 base::MessageLoopProxy::current(),
486 base::TimeTicks::Now()));
487 view
->CopyFromCompositingSurfaceToVideoFrame(
488 gfx::Rect(view
->GetViewBounds().size()),
490 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered
,
491 base::Unretained(this),
492 base::MessageLoopProxy::current(),
493 run_loop
.QuitClosure(),
494 base::TimeTicks::Now()));
497 EXPECT_EQ(2, callback_invoke_count());
498 EXPECT_EQ(2, frames_captured());
501 class CompositingRenderWidgetHostViewBrowserTestTabCapture
502 : public CompositingRenderWidgetHostViewBrowserTest
{
504 CompositingRenderWidgetHostViewBrowserTestTabCapture()
505 : expected_copy_from_compositing_surface_result_(false),
507 test_url_("data:text/html,<!doctype html>") {}
509 virtual void SetUp() OVERRIDE
{
511 CompositingRenderWidgetHostViewBrowserTest::SetUp();
514 void CopyFromCompositingSurfaceCallback(base::Closure quit_callback
,
516 const SkBitmap
& bitmap
) {
517 EXPECT_EQ(expected_copy_from_compositing_surface_result_
, result
);
523 const SkBitmap
& expected_bitmap
=
524 expected_copy_from_compositing_surface_bitmap_
;
525 EXPECT_EQ(expected_bitmap
.width(), bitmap
.width());
526 EXPECT_EQ(expected_bitmap
.height(), bitmap
.height());
527 EXPECT_EQ(expected_bitmap
.config(), bitmap
.config());
528 SkAutoLockPixels
expected_bitmap_lock(expected_bitmap
);
529 SkAutoLockPixels
bitmap_lock(bitmap
);
531 for (int i
= 0; i
< bitmap
.width() && fails
< 10; ++i
) {
532 for (int j
= 0; j
< bitmap
.height() && fails
< 10; ++j
) {
533 if (!exclude_rect_
.IsEmpty() && exclude_rect_
.Contains(i
, j
))
536 SkColor expected_color
= expected_bitmap
.getColor(i
, j
);
537 SkColor color
= bitmap
.getColor(i
, j
);
538 int expected_alpha
= SkColorGetA(expected_color
);
539 int alpha
= SkColorGetA(color
);
540 int expected_red
= SkColorGetR(expected_color
);
541 int red
= SkColorGetR(color
);
542 int expected_green
= SkColorGetG(expected_color
);
543 int green
= SkColorGetG(color
);
544 int expected_blue
= SkColorGetB(expected_color
);
545 int blue
= SkColorGetB(color
);
546 EXPECT_NEAR(expected_alpha
, alpha
, allowable_error_
)
547 << "expected_color: " << std::hex
<< expected_color
548 << " color: " << color
549 << " Failed at " << std::dec
<< i
<< ", " << j
550 << " Failure " << ++fails
;
551 EXPECT_NEAR(expected_red
, red
, allowable_error_
)
552 << "expected_color: " << std::hex
<< expected_color
553 << " color: " << color
554 << " Failed at " << std::dec
<< i
<< ", " << j
555 << " Failure " << ++fails
;
556 EXPECT_NEAR(expected_green
, green
, allowable_error_
)
557 << "expected_color: " << std::hex
<< expected_color
558 << " color: " << color
559 << " Failed at " << std::dec
<< i
<< ", " << j
560 << " Failure " << ++fails
;
561 EXPECT_NEAR(expected_blue
, blue
, allowable_error_
)
562 << "expected_color: " << std::hex
<< expected_color
563 << " color: " << color
564 << " Failed at " << std::dec
<< i
<< ", " << j
565 << " Failure " << ++fails
;
568 EXPECT_LT(fails
, 10);
573 void CopyFromCompositingSurfaceCallbackForVideo(
574 scoped_refptr
<media::VideoFrame
> video_frame
,
575 base::Closure quit_callback
,
577 EXPECT_EQ(expected_copy_from_compositing_surface_result_
, result
);
583 media::SkCanvasVideoRenderer video_renderer
;
586 bitmap
.allocPixels(SkImageInfo::Make(video_frame
->visible_rect().width(),
587 video_frame
->visible_rect().height(),
588 kPMColor_SkColorType
,
589 kOpaque_SkAlphaType
));
590 bitmap
.allocPixels();
591 SkCanvas
canvas(bitmap
);
593 video_renderer
.Paint(video_frame
.get(),
595 video_frame
->visible_rect(),
598 CopyFromCompositingSurfaceCallback(quit_callback
,
603 void SetExpectedCopyFromCompositingSurfaceResult(bool result
,
604 const SkBitmap
& bitmap
) {
605 expected_copy_from_compositing_surface_result_
= result
;
606 expected_copy_from_compositing_surface_bitmap_
= bitmap
;
609 void SetAllowableError(int amount
) { allowable_error_
= amount
; }
610 void SetExcludeRect(gfx::Rect exclude
) { exclude_rect_
= exclude
; }
612 virtual GURL
TestUrl() OVERRIDE
{
613 return GURL(test_url_
);
616 void SetTestUrl(std::string url
) { test_url_
= url
; }
618 // Loads a page two boxes side-by-side, each half the width of
619 // |html_rect_size|, and with different background colors. The test then
620 // copies from |copy_rect| region of the page into a bitmap of size
621 // |output_size|, and compares that with a bitmap of size
622 // |expected_bitmap_size|.
623 // Note that |output_size| may not have the same size as |copy_rect| (e.g.
624 // when the output is scaled). Also note that |expected_bitmap_size| may not
625 // be the same as |output_size| (e.g. when the device scale factor is not 1).
626 void PerformTestWithLeftRightRects(const gfx::Size
& html_rect_size
,
627 const gfx::Rect
& copy_rect
,
628 const gfx::Size
& output_size
,
629 const gfx::Size
& expected_bitmap_size
,
631 const gfx::Size
box_size(html_rect_size
.width() / 2,
632 html_rect_size
.height());
633 SetTestUrl(base::StringPrintf(
634 "data:text/html,<!doctype html>"
636 " <div class='right'></div>"
639 "body { padding: 0; margin: 0; }"
640 ".left { position: absolute;"
645 ".right { position: absolute;"
653 " domAutomationController.setAutomationId(0);"
654 " domAutomationController.send(\"DONE\");"
662 SET_UP_SURFACE_OR_PASS_TEST("\"DONE\"");
663 if (!ShouldContinueAfterTestURLLoad())
666 RenderWidgetHostViewPort
* rwhvp
= GetRenderWidgetHostViewPort();
667 if (video_frame
&& !rwhvp
->CanCopyToVideoFrame()) {
668 // This should only happen on Mac when using the software compositor.
669 // Otherwise, raise an error. This can be removed when Mac is moved to a
670 // browser compositor.
671 // http://crbug.com/314190
672 #if defined(OS_MACOSX)
673 if (!content::GpuDataManager::GetInstance()->GpuAccessAllowed(NULL
)) {
674 LOG(WARNING
) << ("Blindly passing this test because copying to "
675 "video frames is not supported on this platform.");
682 // The page is loaded in the renderer, wait for a new frame to arrive.
683 uint32 frame
= rwhvp
->RendererFrameNumber();
684 while (!GetRenderWidgetHost()->ScheduleComposite())
686 while (rwhvp
->RendererFrameNumber() == frame
)
689 SkBitmap expected_bitmap
;
690 SetupLeftRightBitmap(expected_bitmap_size
, &expected_bitmap
);
691 SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap
);
693 base::RunLoop run_loop
;
695 // Allow pixel differences as long as we have the right idea.
696 SetAllowableError(0x10);
697 // Exclude the middle two columns which are blended between the two sides.
699 gfx::Rect(output_size
.width() / 2 - 1, 0, 2, output_size
.height()));
701 scoped_refptr
<media::VideoFrame
> video_frame
=
702 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
,
703 expected_bitmap_size
,
704 gfx::Rect(expected_bitmap_size
),
705 expected_bitmap_size
,
708 base::Callback
<void(bool success
)> callback
=
709 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
710 CopyFromCompositingSurfaceCallbackForVideo
,
711 base::Unretained(this),
713 run_loop
.QuitClosure());
714 rwhvp
->CopyFromCompositingSurfaceToVideoFrame(copy_rect
,
718 #if defined(USE_AURA)
719 if (!content::GpuDataManager::GetInstance()
720 ->CanUseGpuBrowserCompositor()) {
721 // Skia rendering can cause color differences, particularly in the
722 // middle two columns.
723 SetAllowableError(2);
725 gfx::Rect(output_size
.width() / 2 - 1, 0, 2, output_size
.height()));
729 base::Callback
<void(bool, const SkBitmap
&)> callback
=
730 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
731 CopyFromCompositingSurfaceCallback
,
732 base::Unretained(this),
733 run_loop
.QuitClosure());
734 rwhvp
->CopyFromCompositingSurface(copy_rect
,
737 SkBitmap::kARGB_8888_Config
);
742 // Sets up |bitmap| to have size |copy_size|. It floods the left half with
743 // #0ff and the right half with #ff0.
744 void SetupLeftRightBitmap(const gfx::Size
& copy_size
, SkBitmap
* bitmap
) {
746 SkBitmap::kARGB_8888_Config
, copy_size
.width(), copy_size
.height());
747 bitmap
->allocPixels();
748 // Left half is #0ff.
749 bitmap
->eraseARGB(255, 0, 255, 255);
750 // Right half is #ff0.
752 SkAutoLockPixels
lock(*bitmap
);
753 for (int i
= 0; i
< copy_size
.width() / 2; ++i
) {
754 for (int j
= 0; j
< copy_size
.height(); ++j
) {
755 *(bitmap
->getAddr32(copy_size
.width() / 2 + i
, j
)) =
756 SkColorSetARGB(255, 255, 255, 0);
763 virtual bool ShouldContinueAfterTestURLLoad() {
768 bool expected_copy_from_compositing_surface_result_
;
769 SkBitmap expected_copy_from_compositing_surface_bitmap_
;
770 int allowable_error_
;
771 gfx::Rect exclude_rect_
;
772 std::string test_url_
;
775 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
776 CopyFromCompositingSurface_Origin_Unscaled
) {
777 gfx::Rect
copy_rect(400, 300);
778 gfx::Size output_size
= copy_rect
.size();
779 gfx::Size expected_bitmap_size
= output_size
;
780 gfx::Size
html_rect_size(400, 300);
781 bool video_frame
= false;
782 PerformTestWithLeftRightRects(html_rect_size
,
785 expected_bitmap_size
,
789 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
790 CopyFromCompositingSurface_Origin_Scaled
) {
791 gfx::Rect
copy_rect(400, 300);
792 gfx::Size
output_size(200, 100);
793 gfx::Size expected_bitmap_size
= output_size
;
794 gfx::Size
html_rect_size(400, 300);
795 bool video_frame
= false;
796 PerformTestWithLeftRightRects(html_rect_size
,
799 expected_bitmap_size
,
803 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
804 CopyFromCompositingSurface_Cropped_Unscaled
) {
805 // Grab 60x60 pixels from the center of the tab contents.
806 gfx::Rect
copy_rect(400, 300);
807 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(30, 30),
809 gfx::Size output_size
= copy_rect
.size();
810 gfx::Size expected_bitmap_size
= output_size
;
811 gfx::Size
html_rect_size(400, 300);
812 bool video_frame
= false;
813 PerformTestWithLeftRightRects(html_rect_size
,
816 expected_bitmap_size
,
820 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
821 CopyFromCompositingSurface_Cropped_Scaled
) {
822 // Grab 60x60 pixels from the center of the tab contents.
823 gfx::Rect
copy_rect(400, 300);
824 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(30, 30),
826 gfx::Size
output_size(20, 10);
827 gfx::Size expected_bitmap_size
= output_size
;
828 gfx::Size
html_rect_size(400, 300);
829 bool video_frame
= false;
830 PerformTestWithLeftRightRects(html_rect_size
,
833 expected_bitmap_size
,
837 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
838 CopyFromCompositingSurface_ForVideoFrame
) {
839 // Grab 90x60 pixels from the center of the tab contents.
840 gfx::Rect
copy_rect(400, 300);
841 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(45, 30),
843 gfx::Size output_size
= copy_rect
.size();
844 gfx::Size expected_bitmap_size
= output_size
;
845 gfx::Size
html_rect_size(400, 300);
846 bool video_frame
= true;
847 PerformTestWithLeftRightRects(html_rect_size
,
850 expected_bitmap_size
,
854 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
855 CopyFromCompositingSurface_ForVideoFrame_Scaled
) {
856 // Grab 90x60 pixels from the center of the tab contents.
857 gfx::Rect
copy_rect(400, 300);
858 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(45, 30),
860 // Scale to 30 x 20 (preserve aspect ratio).
861 gfx::Size
output_size(30, 20);
862 gfx::Size expected_bitmap_size
= output_size
;
863 gfx::Size
html_rect_size(400, 300);
864 bool video_frame
= true;
865 PerformTestWithLeftRightRects(html_rect_size
,
868 expected_bitmap_size
,
872 class CompositingRenderWidgetHostViewTabCaptureHighDPI
873 : public CompositingRenderWidgetHostViewBrowserTestTabCapture
{
875 CompositingRenderWidgetHostViewTabCaptureHighDPI() : kScale(2.f
) {}
877 virtual void SetUpOnMainThread() OVERRIDE
{
878 CommandLine
* cmd
= CommandLine::ForCurrentProcess();
879 cmd
->AppendSwitchASCII(switches::kForceDeviceScaleFactor
,
880 base::StringPrintf("%f", scale()));
882 gfx::ForceHighDPISupportForTesting(scale());
883 gfx::EnableHighDPISupport();
887 float scale() const { return kScale
; }
890 virtual bool ShouldContinueAfterTestURLLoad() OVERRIDE
{
891 PASS_TEST_IF_SCALE_FACTOR_NOT_SUPPORTED(scale());
897 DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewTabCaptureHighDPI
);
900 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewTabCaptureHighDPI
,
901 CopyFromCompositingSurface
) {
902 gfx::Rect
copy_rect(200, 150);
903 gfx::Size output_size
= copy_rect
.size();
904 gfx::Size expected_bitmap_size
=
905 gfx::ToFlooredSize(gfx::ScaleSize(output_size
, scale(), scale()));
906 gfx::Size
html_rect_size(200, 150);
907 bool video_frame
= false;
908 PerformTestWithLeftRightRects(html_rect_size
,
911 expected_bitmap_size
,
915 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewTabCaptureHighDPI
,
916 CopyFromCompositingSurfaceVideoFrame
) {
917 gfx::Size
html_rect_size(200, 150);
918 // Grab 90x60 pixels from the center of the tab contents.
919 gfx::Rect copy_rect
=
920 gfx::Rect(gfx::Rect(html_rect_size
).CenterPoint() - gfx::Vector2d(45, 30),
922 gfx::Size output_size
= copy_rect
.size();
923 gfx::Size expected_bitmap_size
=
924 gfx::ToFlooredSize(gfx::ScaleSize(output_size
, scale(), scale()));
925 bool video_frame
= true;
926 PerformTestWithLeftRightRects(html_rect_size
,
929 expected_bitmap_size
,
933 #if !defined(USE_AURA) && !defined(OS_MACOSX)
934 // TODO(danakj): Remove this case when GTK linux is no more and move the
935 // values inline to testing::Values() below.
936 static const CompositingMode kAllCompositingModes
[] = {GL_COMPOSITING
};
938 static const CompositingMode kAllCompositingModes
[] = {GL_COMPOSITING
,
939 SOFTWARE_COMPOSITING
};
942 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing
,
943 CompositingRenderWidgetHostViewBrowserTest
,
944 testing::ValuesIn(kAllCompositingModes
));
945 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing
,
946 CompositingRenderWidgetHostViewBrowserTestTabCapture
,
947 testing::ValuesIn(kAllCompositingModes
));
948 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing
,
949 CompositingRenderWidgetHostViewTabCaptureHighDPI
,
950 testing::ValuesIn(kAllCompositingModes
));
952 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
955 } // namespace content