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::Time 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 class CompositingRenderWidgetHostViewBrowserTest
215 : public RenderWidgetHostViewBrowserTest
{
217 virtual void SetUp() OVERRIDE
{
218 // We expect real pixel output for these tests.
221 // On legacy windows, these tests need real GL bindings to pass.
222 #if defined(OS_WIN) && !defined(USE_AURA)
226 RenderWidgetHostViewBrowserTest::SetUp();
229 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
230 // Note: Not appending kForceCompositingMode switch here, since not all bots
231 // support compositing. Some bots will run with compositing on, and others
232 // won't. Therefore, the call to SetUpSourceSurface() later on will detect
233 // whether compositing mode is actually on or not. If not, the tests will
234 // pass blindly, logging a warning message, since we cannot test what the
235 // platform/implementation does not support.
236 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line
);
239 virtual GURL
TestUrl() {
240 return net::FilePathToFileURL(
241 test_dir().AppendASCII("rwhv_compositing_animation.html"));
244 virtual bool SetUpSourceSurface(const char* wait_message
) OVERRIDE
{
245 if (!IsForceCompositingModeEnabled())
246 return false; // See comment in SetUpCommandLine().
247 #if defined(OS_MACOSX)
248 CHECK(IOSurfaceSupport::Initialize());
251 content::DOMMessageQueue message_queue
;
252 NavigateToURL(shell(), TestUrl());
253 if (wait_message
!= NULL
) {
254 std::string
result(wait_message
);
255 if (!message_queue
.WaitForMessage(&result
)) {
256 EXPECT_TRUE(false) << "WaitForMessage " << result
<< " failed.";
261 #if !defined(USE_AURA)
262 if (!GetRenderWidgetHost()->is_accelerated_compositing_active())
263 return false; // Renderer did not turn on accelerated compositing.
266 // Using accelerated compositing, but a compositing surface might not be
267 // available yet. So, wait for it.
268 WaitForCopySourceReady();
273 class NonCompositingRenderWidgetHostViewBrowserTest
274 : public RenderWidgetHostViewBrowserTest
{
276 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
277 // Note: Appending the kDisableAcceleratedCompositing switch here, but there
278 // are some builds that only use compositing and will ignore this switch.
279 // Therefore, the call to SetUpSourceSurface() later on will detect whether
280 // compositing mode is actually off. If it's on, the tests will pass
281 // blindly, logging a warning message, since we cannot test what the
282 // platform/implementation does not support.
283 command_line
->AppendSwitch(switches::kDisableAcceleratedCompositing
);
284 RenderWidgetHostViewBrowserTest::SetUpCommandLine(command_line
);
287 virtual GURL
TestUrl() {
288 return GURL(kAboutBlankURL
);
291 virtual bool SetUpSourceSurface(const char* wait_message
) OVERRIDE
{
292 if (IsForceCompositingModeEnabled())
293 return false; // See comment in SetUpCommandLine().
295 content::DOMMessageQueue message_queue
;
296 NavigateToURL(shell(), TestUrl());
297 if (wait_message
!= NULL
) {
298 std::string
result(wait_message
);
299 if (!message_queue
.WaitForMessage(&result
)) {
300 EXPECT_TRUE(false) << "WaitForMessage " << result
<< " failed.";
305 WaitForCopySourceReady();
306 // Return whether the renderer left accelerated compositing turned off.
307 return !GetRenderWidgetHost()->is_accelerated_compositing_active();
311 class FakeFrameSubscriber
: public RenderWidgetHostViewFrameSubscriber
{
314 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback
)
315 : callback_(callback
) {
318 virtual bool ShouldCaptureFrame(
319 base::Time present_time
,
320 scoped_refptr
<media::VideoFrame
>* storage
,
321 DeliverFrameCallback
* callback
) OVERRIDE
{
322 // Only allow one frame capture to be made. Otherwise, the compositor could
323 // start multiple captures, unbounded, and eventually its own limiter logic
324 // will begin invoking |callback| with a |false| result. This flakes out
325 // the unit tests, since they receive a "failed" callback before the later
326 // "success" callbacks.
327 if (callback_
.is_null())
329 *storage
= media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
330 *callback
= callback_
;
336 DeliverFrameCallback callback_
;
339 // Disable tests for Android and IOS as these platforms have incomplete
341 #if !defined(OS_ANDROID) && !defined(OS_IOS)
343 // The CopyFromBackingStore() API should work on all platforms when compositing
345 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest
,
346 CopyFromBackingStore
) {
347 RunBasicCopyFromBackingStoreTest();
350 // The CopyFromBackingStore() API should work on all platforms when compositing
352 IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest
,
353 CopyFromBackingStore
) {
354 RunBasicCopyFromBackingStoreTest();
357 // Tests that the callback passed to CopyFromBackingStore is always called,
358 // even when the RenderWidgetHost is deleting in the middle of an async copy.
359 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest
,
360 CopyFromBackingStore_CallbackDespiteDelete
) {
361 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
363 base::RunLoop run_loop
;
364 GetRenderViewHost()->CopyFromBackingStore(
367 base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore
,
368 base::Unretained(this), run_loop
.QuitClosure()));
369 // Delete the surface before the callback is run.
370 GetRenderWidgetHostViewPort()->AcceleratedSurfaceRelease();
373 EXPECT_EQ(1, callback_invoke_count());
376 // Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is
377 // always called, even when the RenderWidgetHost is deleting in the middle of
380 // Test is flaky on Win Aura. http://crbug.com/276783
381 #if (defined(OS_WIN) && defined(USE_AURA)) || \
382 (defined(OS_CHROMEOS) && !defined(NDEBUG))
383 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
384 DISABLED_CopyFromCompositingSurface_CallbackDespiteDelete
386 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
387 CopyFromCompositingSurface_CallbackDespiteDelete
389 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest
,
390 MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete
) {
391 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
392 RenderWidgetHostViewPort
* const view
= GetRenderWidgetHostViewPort();
393 if (!view
->CanCopyToVideoFrame()) {
395 ("Blindly passing this test: CopyFromCompositingSurfaceToVideoFrame() "
396 "not supported on this platform.");
400 base::RunLoop run_loop
;
401 scoped_refptr
<media::VideoFrame
> dest
=
402 media::VideoFrame::CreateBlackFrame(frame_size());
403 view
->CopyFromCompositingSurfaceToVideoFrame(
404 gfx::Rect(view
->GetViewBounds().size()), dest
, base::Bind(
405 &RenderWidgetHostViewBrowserTest::FinishCopyFromCompositingSurface
,
406 base::Unretained(this), run_loop
.QuitClosure()));
407 // Delete the surface before the callback is run.
408 view
->AcceleratedSurfaceRelease();
411 EXPECT_EQ(1, callback_invoke_count());
414 // With compositing turned off, no platforms should support the
415 // CopyFromCompositingSurfaceToVideoFrame() API.
416 IN_PROC_BROWSER_TEST_F(NonCompositingRenderWidgetHostViewBrowserTest
,
417 CopyFromCompositingSurfaceToVideoFrameCallbackTest
) {
418 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
419 EXPECT_FALSE(GetRenderWidgetHostViewPort()->CanCopyToVideoFrame());
422 // Test basic frame subscription functionality. We subscribe, and then run
423 // until at least one DeliverFrameCallback has been invoked.
424 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest
,
425 FrameSubscriberTest
) {
426 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
427 RenderWidgetHostViewPort
* const view
= GetRenderWidgetHostViewPort();
428 if (!view
->CanSubscribeFrame()) {
429 LOG(WARNING
) << ("Blindly passing this test: Frame subscription not "
430 "supported on this platform.");
434 base::RunLoop run_loop
;
435 scoped_ptr
<RenderWidgetHostViewFrameSubscriber
> subscriber(
436 new FakeFrameSubscriber(
437 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered
,
438 base::Unretained(this),
439 base::MessageLoopProxy::current(),
440 run_loop
.QuitClosure())));
441 view
->BeginFrameSubscription(subscriber
.Pass());
443 view
->EndFrameSubscription();
445 EXPECT_LE(1, callback_invoke_count());
446 EXPECT_LE(1, frames_captured());
449 // Test that we can copy twice from an accelerated composited page.
450 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTest
, CopyTwice
) {
451 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
452 RenderWidgetHostViewPort
* const view
= GetRenderWidgetHostViewPort();
453 if (!view
->CanCopyToVideoFrame()) {
454 LOG(WARNING
) << ("Blindly passing this test: "
455 "CopyFromCompositingSurfaceToVideoFrame() not supported "
456 "on this platform.");
460 base::RunLoop run_loop
;
461 scoped_refptr
<media::VideoFrame
> first_output
=
462 media::VideoFrame::CreateBlackFrame(frame_size());
463 ASSERT_TRUE(first_output
.get());
464 scoped_refptr
<media::VideoFrame
> second_output
=
465 media::VideoFrame::CreateBlackFrame(frame_size());
466 ASSERT_TRUE(second_output
.get());
467 view
->CopyFromCompositingSurfaceToVideoFrame(
468 gfx::Rect(view
->GetViewBounds().size()),
470 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered
,
471 base::Unretained(this),
472 base::MessageLoopProxy::current(),
475 view
->CopyFromCompositingSurfaceToVideoFrame(
476 gfx::Rect(view
->GetViewBounds().size()), second_output
,
477 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered
,
478 base::Unretained(this),
479 base::MessageLoopProxy::current(),
480 run_loop
.QuitClosure(),
484 EXPECT_EQ(2, callback_invoke_count());
485 EXPECT_EQ(2, frames_captured());
488 class CompositingRenderWidgetHostViewBrowserTestTabCapture
489 : public CompositingRenderWidgetHostViewBrowserTest
{
491 CompositingRenderWidgetHostViewBrowserTestTabCapture()
492 : expected_copy_from_compositing_surface_result_(false),
494 test_url_("data:text/html,<!doctype html>") {}
496 void CopyFromCompositingSurfaceCallback(base::Closure quit_callback
,
498 const SkBitmap
& bitmap
) {
499 EXPECT_EQ(expected_copy_from_compositing_surface_result_
, result
);
505 const SkBitmap
& expected_bitmap
=
506 expected_copy_from_compositing_surface_bitmap_
;
507 EXPECT_EQ(expected_bitmap
.width(), bitmap
.width());
508 EXPECT_EQ(expected_bitmap
.height(), bitmap
.height());
509 EXPECT_EQ(expected_bitmap
.config(), bitmap
.config());
510 SkAutoLockPixels
expected_bitmap_lock(expected_bitmap
);
511 SkAutoLockPixels
bitmap_lock(bitmap
);
513 for (int i
= 0; i
< bitmap
.width() && fails
< 10; ++i
) {
514 for (int j
= 0; j
< bitmap
.height() && fails
< 10; ++j
) {
515 if (!exclude_rect_
.IsEmpty() && exclude_rect_
.Contains(i
, j
))
518 SkColor expected_color
= expected_bitmap
.getColor(i
, j
);
519 SkColor color
= bitmap
.getColor(i
, j
);
520 int expected_alpha
= SkColorGetA(expected_color
);
521 int alpha
= SkColorGetA(color
);
522 int expected_red
= SkColorGetR(expected_color
);
523 int red
= SkColorGetR(color
);
524 int expected_green
= SkColorGetG(expected_color
);
525 int green
= SkColorGetG(color
);
526 int expected_blue
= SkColorGetB(expected_color
);
527 int blue
= SkColorGetB(color
);
528 EXPECT_NEAR(expected_alpha
, alpha
, allowable_error_
)
529 << "expected_color: " << std::hex
<< expected_color
530 << " color: " << color
531 << " Failed at " << std::dec
<< i
<< ", " << j
532 << " Failure " << ++fails
;
533 EXPECT_NEAR(expected_red
, red
, allowable_error_
)
534 << "expected_color: " << std::hex
<< expected_color
535 << " color: " << color
536 << " Failed at " << std::dec
<< i
<< ", " << j
537 << " Failure " << ++fails
;
538 EXPECT_NEAR(expected_green
, green
, allowable_error_
)
539 << "expected_color: " << std::hex
<< expected_color
540 << " color: " << color
541 << " Failed at " << std::dec
<< i
<< ", " << j
542 << " Failure " << ++fails
;
543 EXPECT_NEAR(expected_blue
, blue
, allowable_error_
)
544 << "expected_color: " << std::hex
<< expected_color
545 << " color: " << color
546 << " Failed at " << std::dec
<< i
<< ", " << j
547 << " Failure " << ++fails
;
550 EXPECT_LT(fails
, 10);
555 void CopyFromCompositingSurfaceCallbackForVideo(
556 scoped_refptr
<media::VideoFrame
> video_frame
,
557 base::Closure quit_callback
,
559 EXPECT_EQ(expected_copy_from_compositing_surface_result_
, result
);
565 media::SkCanvasVideoRenderer video_renderer
;
568 bitmap
.setConfig(SkBitmap::kARGB_8888_Config
,
569 video_frame
->visible_rect().width(),
570 video_frame
->visible_rect().height(),
571 0, kOpaque_SkAlphaType
);
572 bitmap
.allocPixels();
574 SkBitmapDevice
device(bitmap
);
575 SkCanvas
canvas(&device
);
577 video_renderer
.Paint(video_frame
.get(),
579 video_frame
->visible_rect(),
582 CopyFromCompositingSurfaceCallback(quit_callback
,
587 void SetExpectedCopyFromCompositingSurfaceResult(bool result
,
588 const SkBitmap
& bitmap
) {
589 expected_copy_from_compositing_surface_result_
= result
;
590 expected_copy_from_compositing_surface_bitmap_
= bitmap
;
593 void SetAllowableError(int amount
) { allowable_error_
= amount
; }
594 void SetExcludeRect(gfx::Rect exclude
) { exclude_rect_
= exclude
; }
596 virtual GURL
TestUrl() OVERRIDE
{
597 return GURL(test_url_
);
600 void SetTestUrl(std::string url
) { test_url_
= url
; }
602 // Loads a page two boxes side-by-side, each half the width of
603 // |html_rect_size|, and with different background colors. The test then
604 // copies from |copy_rect| region of the page into a bitmap of size
605 // |output_size|, and compares that with a bitmap of size
606 // |expected_bitmap_size|.
607 // Note that |output_size| may not have the same size as |copy_rect| (e.g.
608 // when the output is scaled). Also note that |expected_bitmap_size| may not
609 // be the same as |output_size| (e.g. when the device scale factor is not 1).
610 void PerformTestWithLeftRightRects(const gfx::Size
& html_rect_size
,
611 const gfx::Rect
& copy_rect
,
612 const gfx::Size
& output_size
,
613 const gfx::Size
& expected_bitmap_size
,
615 const gfx::Size
box_size(html_rect_size
.width() / 2,
616 html_rect_size
.height());
617 SetTestUrl(base::StringPrintf(
618 "data:text/html,<!doctype html>"
620 " <div class='right'></div>"
623 "body { padding: 0; margin: 0; }"
624 ".left { position: absolute;"
629 ".right { position: absolute;"
637 " domAutomationController.setAutomationId(0);"
638 " domAutomationController.send(\"DONE\");"
646 SET_UP_SURFACE_OR_PASS_TEST("\"DONE\"");
647 if (!ShouldContinueAfterTestURLLoad())
650 RenderWidgetHostViewPort
* rwhvp
= GetRenderWidgetHostViewPort();
652 // The page is loaded in the renderer, wait for a new frame to arrive.
653 uint32 frame
= rwhvp
->RendererFrameNumber();
654 while (!GetRenderWidgetHost()->ScheduleComposite())
656 while (rwhvp
->RendererFrameNumber() == frame
)
659 SkBitmap expected_bitmap
;
660 SetupLeftRightBitmap(expected_bitmap_size
, &expected_bitmap
);
661 SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap
);
663 base::RunLoop run_loop
;
665 // Allow pixel differences as long as we have the right idea.
666 SetAllowableError(0x10);
667 // Exclude the middle two columns which are blended between the two sides.
669 gfx::Rect(output_size
.width() / 2 - 1, 0, 2, output_size
.height()));
671 scoped_refptr
<media::VideoFrame
> video_frame
=
672 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
,
673 expected_bitmap_size
,
674 gfx::Rect(expected_bitmap_size
),
675 expected_bitmap_size
,
678 base::Callback
<void(bool success
)> callback
=
679 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
680 CopyFromCompositingSurfaceCallbackForVideo
,
681 base::Unretained(this),
683 run_loop
.QuitClosure());
684 rwhvp
->CopyFromCompositingSurfaceToVideoFrame(copy_rect
,
688 #if defined(USE_AURA)
689 if (!content::GpuDataManager::GetInstance()
690 ->CanUseGpuBrowserCompositor()) {
691 // Skia rendering can cause color differences, particularly in the
692 // middle two columns.
693 SetAllowableError(2);
695 gfx::Rect(output_size
.width() / 2 - 1, 0, 2, output_size
.height()));
699 base::Callback
<void(bool, const SkBitmap
&)> callback
=
700 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
701 CopyFromCompositingSurfaceCallback
,
702 base::Unretained(this),
703 run_loop
.QuitClosure());
704 rwhvp
->CopyFromCompositingSurface(copy_rect
, output_size
, callback
);
709 // Sets up |bitmap| to have size |copy_size|. It floods the left half with
710 // #0ff and the right half with #ff0.
711 void SetupLeftRightBitmap(const gfx::Size
& copy_size
, SkBitmap
* bitmap
) {
713 SkBitmap::kARGB_8888_Config
, copy_size
.width(), copy_size
.height());
714 bitmap
->allocPixels();
715 // Left half is #0ff.
716 bitmap
->eraseARGB(255, 0, 255, 255);
717 // Right half is #ff0.
719 SkAutoLockPixels
lock(*bitmap
);
720 for (int i
= 0; i
< copy_size
.width() / 2; ++i
) {
721 for (int j
= 0; j
< copy_size
.height(); ++j
) {
722 *(bitmap
->getAddr32(copy_size
.width() / 2 + i
, j
)) =
723 SkColorSetARGB(255, 255, 255, 0);
730 virtual bool ShouldContinueAfterTestURLLoad() {
735 bool expected_copy_from_compositing_surface_result_
;
736 SkBitmap expected_copy_from_compositing_surface_bitmap_
;
737 int allowable_error_
;
738 gfx::Rect exclude_rect_
;
739 std::string test_url_
;
742 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
743 CopyFromCompositingSurface_Origin_Unscaled
) {
744 gfx::Rect
copy_rect(400, 300);
745 gfx::Size output_size
= copy_rect
.size();
746 gfx::Size expected_bitmap_size
= output_size
;
747 gfx::Size
html_rect_size(400, 300);
748 bool video_frame
= false;
749 PerformTestWithLeftRightRects(html_rect_size
,
752 expected_bitmap_size
,
756 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
757 CopyFromCompositingSurface_Origin_Scaled
) {
758 gfx::Rect
copy_rect(400, 300);
759 gfx::Size
output_size(200, 100);
760 gfx::Size expected_bitmap_size
= output_size
;
761 gfx::Size
html_rect_size(400, 300);
762 bool video_frame
= false;
763 PerformTestWithLeftRightRects(html_rect_size
,
766 expected_bitmap_size
,
770 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
771 CopyFromCompositingSurface_Cropped_Unscaled
) {
772 // Grab 60x60 pixels from the center of the tab contents.
773 gfx::Rect
copy_rect(400, 300);
774 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(30, 30),
776 gfx::Size output_size
= copy_rect
.size();
777 gfx::Size expected_bitmap_size
= output_size
;
778 gfx::Size
html_rect_size(400, 300);
779 bool video_frame
= false;
780 PerformTestWithLeftRightRects(html_rect_size
,
783 expected_bitmap_size
,
787 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
788 CopyFromCompositingSurface_Cropped_Scaled
) {
789 // Grab 60x60 pixels from the center of the tab contents.
790 gfx::Rect
copy_rect(400, 300);
791 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(30, 30),
793 gfx::Size
output_size(20, 10);
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_F(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
805 CopyFromCompositingSurface_ForVideoFrame
) {
806 // Grab 90x60 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(45, 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
= true;
814 PerformTestWithLeftRightRects(html_rect_size
,
817 expected_bitmap_size
,
821 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
822 CopyFromCompositingSurface_ForVideoFrame_Scaled
) {
823 // Grab 90x60 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(45, 30),
827 // Scale to 30 x 20 (preserve aspect ratio).
828 gfx::Size
output_size(30, 20);
829 gfx::Size expected_bitmap_size
= output_size
;
830 gfx::Size
html_rect_size(400, 300);
831 bool video_frame
= true;
832 PerformTestWithLeftRightRects(html_rect_size
,
835 expected_bitmap_size
,
839 class CompositingRenderWidgetHostViewTabCaptureHighDPI
840 : public CompositingRenderWidgetHostViewBrowserTestTabCapture
{
842 CompositingRenderWidgetHostViewTabCaptureHighDPI()
846 virtual void SetUpCommandLine(CommandLine
* cmd
) OVERRIDE
{
847 CompositingRenderWidgetHostViewBrowserTestTabCapture::SetUpCommandLine(cmd
);
848 cmd
->AppendSwitchASCII(switches::kForceDeviceScaleFactor
,
849 base::StringPrintf("%f", scale()));
851 cmd
->AppendSwitchASCII(switches::kHighDPISupport
, "1");
852 gfx::EnableHighDPISupport();
856 float scale() const { return kScale
; }
859 virtual bool ShouldContinueAfterTestURLLoad() OVERRIDE
{
860 PASS_TEST_IF_SCALE_FACTOR_NOT_SUPPORTED(scale());
866 DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewTabCaptureHighDPI
);
869 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewTabCaptureHighDPI
,
870 CopyFromCompositingSurface
) {
871 gfx::Rect
copy_rect(200, 150);
872 gfx::Size output_size
= copy_rect
.size();
873 gfx::Size expected_bitmap_size
=
874 gfx::ToFlooredSize(gfx::ScaleSize(output_size
, scale(), scale()));
875 gfx::Size
html_rect_size(200, 150);
876 bool video_frame
= false;
877 PerformTestWithLeftRightRects(html_rect_size
,
880 expected_bitmap_size
,
884 IN_PROC_BROWSER_TEST_F(CompositingRenderWidgetHostViewTabCaptureHighDPI
,
885 CopyFromCompositingSurfaceVideoFrame
) {
886 gfx::Size
html_rect_size(200, 150);
887 // Grab 90x60 pixels from the center of the tab contents.
888 gfx::Rect copy_rect
=
889 gfx::Rect(gfx::Rect(html_rect_size
).CenterPoint() - gfx::Vector2d(45, 30),
891 gfx::Size output_size
= copy_rect
.size();
892 gfx::Size expected_bitmap_size
=
893 gfx::ToFlooredSize(gfx::ScaleSize(output_size
, scale(), scale()));
894 bool video_frame
= true;
895 PerformTestWithLeftRightRects(html_rect_size
,
898 expected_bitmap_size
,
902 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
905 } // namespace content