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/browser/renderer_host/render_widget_host_view_base.h"
14 #include "content/public/browser/gpu_data_manager.h"
15 #include "content/public/browser/render_view_host.h"
16 #include "content/public/browser/render_widget_host_view_frame_subscriber.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/filename_util.h"
28 #include "third_party/skia/include/core/SkBitmap.h"
29 #include "third_party/skia/include/core/SkCanvas.h"
30 #include "ui/base/layout.h"
31 #include "ui/base/ui_base_switches.h"
32 #include "ui/gfx/geometry/size_conversions.h"
33 #include "ui/gfx/switches.h"
34 #include "ui/gl/gl_switches.h"
37 #include "base/win/windows_version.h"
38 #include "ui/gfx/win/dpi.h"
44 // Convenience macro: Short-circuit a pass for the tests where platform support
45 // for forced-compositing mode (or disabled-compositing mode) is lacking.
46 #define SET_UP_SURFACE_OR_PASS_TEST(wait_message) \
47 if (!SetUpSourceSurface(wait_message)) { \
49 << ("Blindly passing this test: This platform does not support " \
50 "forced compositing (or forced-disabled compositing) mode."); \
54 // Common base class for browser tests. This is subclassed twice: Once to test
55 // the browser in forced-compositing mode, and once to test with compositing
57 class RenderWidgetHostViewBrowserTest : public ContentBrowserTest {
59 RenderWidgetHostViewBrowserTest()
60 : frame_size_(400, 300),
61 callback_invoke_count_(0),
62 frames_captured_(0) {}
64 void SetUpOnMainThread() override {
65 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir_));
68 // Attempts to set up the source surface. Returns false if unsupported on the
70 virtual bool SetUpSourceSurface(const char* wait_message) = 0;
72 int callback_invoke_count() const {
73 return callback_invoke_count_;
76 int frames_captured() const {
77 return frames_captured_;
80 const gfx::Size& frame_size() const {
84 const base::FilePath& test_dir() const {
88 RenderViewHost* GetRenderViewHost() const {
89 RenderViewHost* const rvh = shell()->web_contents()->GetRenderViewHost();
94 RenderWidgetHostImpl* GetRenderWidgetHost() const {
95 RenderWidgetHostImpl* const rwh = RenderWidgetHostImpl::From(
96 shell()->web_contents()->GetRenderWidgetHostView()->
97 GetRenderWidgetHost());
102 RenderWidgetHostViewBase* GetRenderWidgetHostView() const {
103 return static_cast<RenderWidgetHostViewBase*>(
104 GetRenderViewHost()->GetView());
107 // Callback when using CopyFromBackingStore() API.
108 void FinishCopyFromBackingStore(const base::Closure& quit_closure,
110 const SkBitmap& bitmap) {
111 ++callback_invoke_count_;
112 if (frame_captured) {
114 EXPECT_FALSE(bitmap.empty());
116 if (!quit_closure.is_null())
120 // Callback when using CopyFromCompositingSurfaceToVideoFrame() API.
121 void FinishCopyFromCompositingSurface(const base::Closure& quit_closure,
122 bool frame_captured) {
123 ++callback_invoke_count_;
126 if (!quit_closure.is_null())
130 // Callback when using frame subscriber API.
131 void FrameDelivered(const scoped_refptr<base::MessageLoopProxy>& loop,
132 base::Closure quit_closure,
133 base::TimeTicks timestamp,
134 bool frame_captured) {
135 ++callback_invoke_count_;
138 if (!quit_closure.is_null())
139 loop->PostTask(FROM_HERE, quit_closure);
142 // Copy one frame using the CopyFromBackingStore API.
143 void RunBasicCopyFromBackingStoreTest() {
144 SET_UP_SURFACE_OR_PASS_TEST(NULL);
146 // Repeatedly call CopyFromBackingStore() since, on some platforms (e.g.,
147 // Windows), the operation will fail until the first "present" has been
149 int count_attempts = 0;
152 base::RunLoop run_loop;
153 GetRenderViewHost()->CopyFromBackingStore(
157 &RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
158 base::Unretained(this),
159 run_loop.QuitClosure()),
163 if (frames_captured())
169 EXPECT_EQ(count_attempts, callback_invoke_count());
170 EXPECT_EQ(1, frames_captured());
174 // Waits until the source is available for copying.
175 void WaitForCopySourceReady() {
176 while (!GetRenderWidgetHostView()->IsSurfaceAvailableForCopy())
180 // Run the current message loop for a short time without unwinding the current
182 static void GiveItSomeTime() {
183 base::RunLoop run_loop;
184 base::MessageLoop::current()->PostDelayedTask(
186 run_loop.QuitClosure(),
187 base::TimeDelta::FromMilliseconds(10));
192 const gfx::Size frame_size_;
193 base::FilePath test_dir_;
194 int callback_invoke_count_;
195 int frames_captured_;
198 enum CompositingMode {
200 SOFTWARE_COMPOSITING,
203 class CompositingRenderWidgetHostViewBrowserTest
204 : public RenderWidgetHostViewBrowserTest,
205 public testing::WithParamInterface<CompositingMode> {
207 explicit CompositingRenderWidgetHostViewBrowserTest()
208 : compositing_mode_(GetParam()) {}
210 void SetUp() override {
211 if (compositing_mode_ == SOFTWARE_COMPOSITING)
212 UseSoftwareCompositing();
213 RenderWidgetHostViewBrowserTest::SetUp();
216 virtual GURL TestUrl() {
217 return net::FilePathToFileURL(
218 test_dir().AppendASCII("rwhv_compositing_animation.html"));
221 bool SetUpSourceSurface(const char* wait_message) override {
222 content::DOMMessageQueue message_queue;
223 NavigateToURL(shell(), TestUrl());
224 if (wait_message != NULL) {
225 std::string result(wait_message);
226 if (!message_queue.WaitForMessage(&result)) {
227 EXPECT_TRUE(false) << "WaitForMessage " << result << " failed.";
232 // A frame might not be available yet. So, wait for it.
233 WaitForCopySourceReady();
238 const CompositingMode compositing_mode_;
240 DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewBrowserTest);
243 class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
246 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback)
247 : callback_(callback) {
250 bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
251 base::TimeTicks present_time,
252 scoped_refptr<media::VideoFrame>* storage,
253 DeliverFrameCallback* callback) override {
254 // Only allow one frame capture to be made. Otherwise, the compositor could
255 // start multiple captures, unbounded, and eventually its own limiter logic
256 // will begin invoking |callback| with a |false| result. This flakes out
257 // the unit tests, since they receive a "failed" callback before the later
258 // "success" callbacks.
259 if (callback_.is_null())
261 *storage = media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
262 *callback = callback_;
268 DeliverFrameCallback callback_;
271 // Disable tests for Android and IOS as these platforms have incomplete
273 #if !defined(OS_ANDROID) && !defined(OS_IOS)
275 // The CopyFromBackingStore() API should work on all platforms when compositing
277 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
278 CopyFromBackingStore) {
279 RunBasicCopyFromBackingStoreTest();
282 // Tests that the callback passed to CopyFromBackingStore is always called,
283 // even when the RenderWidgetHost is deleting in the middle of an async copy.
284 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
285 CopyFromBackingStore_CallbackDespiteDelete) {
286 SET_UP_SURFACE_OR_PASS_TEST(NULL);
288 base::RunLoop run_loop;
289 GetRenderViewHost()->CopyFromBackingStore(
292 base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
293 base::Unretained(this),
294 run_loop.QuitClosure()),
298 EXPECT_EQ(1, callback_invoke_count());
301 // Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is
302 // always called, even when the RenderWidgetHost is deleting in the middle of
305 // Test is flaky on Win. http://crbug.com/276783
306 #if defined(OS_WIN) || (defined(OS_CHROMEOS) && !defined(NDEBUG))
307 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
308 DISABLED_CopyFromCompositingSurface_CallbackDespiteDelete
310 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
311 CopyFromCompositingSurface_CallbackDespiteDelete
313 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
314 MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete) {
315 SET_UP_SURFACE_OR_PASS_TEST(NULL);
316 RenderWidgetHostViewBase* const view = GetRenderWidgetHostView();
317 if (!view->CanCopyToVideoFrame()) {
319 ("Blindly passing this test: CopyFromCompositingSurfaceToVideoFrame() "
320 "not supported on this platform.");
324 base::RunLoop run_loop;
325 scoped_refptr<media::VideoFrame> dest =
326 media::VideoFrame::CreateBlackFrame(frame_size());
327 view->CopyFromCompositingSurfaceToVideoFrame(
328 gfx::Rect(view->GetViewBounds().size()), dest, base::Bind(
329 &RenderWidgetHostViewBrowserTest::FinishCopyFromCompositingSurface,
330 base::Unretained(this), run_loop.QuitClosure()));
333 EXPECT_EQ(1, callback_invoke_count());
336 // Test basic frame subscription functionality. We subscribe, and then run
337 // until at least one DeliverFrameCallback has been invoked.
338 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
339 FrameSubscriberTest) {
340 SET_UP_SURFACE_OR_PASS_TEST(NULL);
341 RenderWidgetHostViewBase* const view = GetRenderWidgetHostView();
342 if (!view->CanSubscribeFrame()) {
343 LOG(WARNING) << ("Blindly passing this test: Frame subscription not "
344 "supported on this platform.");
348 base::RunLoop run_loop;
349 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
350 new FakeFrameSubscriber(
351 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
352 base::Unretained(this),
353 base::MessageLoopProxy::current(),
354 run_loop.QuitClosure())));
355 view->BeginFrameSubscription(subscriber.Pass());
357 view->EndFrameSubscription();
359 EXPECT_LE(1, callback_invoke_count());
360 EXPECT_LE(1, frames_captured());
363 // Test that we can copy twice from an accelerated composited page.
364 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest, CopyTwice) {
365 SET_UP_SURFACE_OR_PASS_TEST(NULL);
366 RenderWidgetHostViewBase* const view = GetRenderWidgetHostView();
367 if (!view->CanCopyToVideoFrame()) {
368 LOG(WARNING) << ("Blindly passing this test: "
369 "CopyFromCompositingSurfaceToVideoFrame() not supported "
370 "on this platform.");
374 base::RunLoop run_loop;
375 scoped_refptr<media::VideoFrame> first_output =
376 media::VideoFrame::CreateBlackFrame(frame_size());
377 ASSERT_TRUE(first_output.get());
378 scoped_refptr<media::VideoFrame> second_output =
379 media::VideoFrame::CreateBlackFrame(frame_size());
380 ASSERT_TRUE(second_output.get());
381 view->CopyFromCompositingSurfaceToVideoFrame(
382 gfx::Rect(view->GetViewBounds().size()),
384 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
385 base::Unretained(this),
386 base::MessageLoopProxy::current(),
388 base::TimeTicks::Now()));
389 view->CopyFromCompositingSurfaceToVideoFrame(
390 gfx::Rect(view->GetViewBounds().size()),
392 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
393 base::Unretained(this),
394 base::MessageLoopProxy::current(),
395 run_loop.QuitClosure(),
396 base::TimeTicks::Now()));
399 EXPECT_EQ(2, callback_invoke_count());
400 EXPECT_EQ(2, frames_captured());
403 class CompositingRenderWidgetHostViewBrowserTestTabCapture
404 : public CompositingRenderWidgetHostViewBrowserTest {
406 CompositingRenderWidgetHostViewBrowserTestTabCapture()
407 : expected_copy_from_compositing_surface_result_(false),
409 test_url_("data:text/html,<!doctype html>") {}
411 void SetUp() override {
413 CompositingRenderWidgetHostViewBrowserTest::SetUp();
416 void CopyFromCompositingSurfaceCallback(base::Closure quit_callback,
418 const SkBitmap& bitmap) {
419 EXPECT_EQ(expected_copy_from_compositing_surface_result_, result);
425 const SkBitmap& expected_bitmap =
426 expected_copy_from_compositing_surface_bitmap_;
427 EXPECT_EQ(expected_bitmap.width(), bitmap.width());
428 EXPECT_EQ(expected_bitmap.height(), bitmap.height());
429 EXPECT_EQ(expected_bitmap.colorType(), bitmap.colorType());
430 SkAutoLockPixels expected_bitmap_lock(expected_bitmap);
431 SkAutoLockPixels bitmap_lock(bitmap);
433 for (int i = 0; i < bitmap.width() && fails < 10; ++i) {
434 for (int j = 0; j < bitmap.height() && fails < 10; ++j) {
435 if (!exclude_rect_.IsEmpty() && exclude_rect_.Contains(i, j))
438 SkColor expected_color = expected_bitmap.getColor(i, j);
439 SkColor color = bitmap.getColor(i, j);
440 int expected_alpha = SkColorGetA(expected_color);
441 int alpha = SkColorGetA(color);
442 int expected_red = SkColorGetR(expected_color);
443 int red = SkColorGetR(color);
444 int expected_green = SkColorGetG(expected_color);
445 int green = SkColorGetG(color);
446 int expected_blue = SkColorGetB(expected_color);
447 int blue = SkColorGetB(color);
448 EXPECT_NEAR(expected_alpha, alpha, allowable_error_)
449 << "expected_color: " << std::hex << expected_color
450 << " color: " << color
451 << " Failed at " << std::dec << i << ", " << j
452 << " Failure " << ++fails;
453 EXPECT_NEAR(expected_red, red, allowable_error_)
454 << "expected_color: " << std::hex << expected_color
455 << " color: " << color
456 << " Failed at " << std::dec << i << ", " << j
457 << " Failure " << ++fails;
458 EXPECT_NEAR(expected_green, green, allowable_error_)
459 << "expected_color: " << std::hex << expected_color
460 << " color: " << color
461 << " Failed at " << std::dec << i << ", " << j
462 << " Failure " << ++fails;
463 EXPECT_NEAR(expected_blue, blue, allowable_error_)
464 << "expected_color: " << std::hex << expected_color
465 << " color: " << color
466 << " Failed at " << std::dec << i << ", " << j
467 << " Failure " << ++fails;
470 EXPECT_LT(fails, 10);
475 void CopyFromCompositingSurfaceCallbackForVideo(
476 scoped_refptr<media::VideoFrame> video_frame,
477 base::Closure quit_callback,
479 EXPECT_EQ(expected_copy_from_compositing_surface_result_, result);
485 media::SkCanvasVideoRenderer video_renderer;
488 bitmap.allocN32Pixels(video_frame->visible_rect().width(),
489 video_frame->visible_rect().height());
490 // Don't clear the canvas because drawing a video frame by Src mode.
491 SkCanvas canvas(bitmap);
492 video_renderer.Copy(video_frame, &canvas);
494 CopyFromCompositingSurfaceCallback(quit_callback,
499 void SetExpectedCopyFromCompositingSurfaceResult(bool result,
500 const SkBitmap& bitmap) {
501 expected_copy_from_compositing_surface_result_ = result;
502 expected_copy_from_compositing_surface_bitmap_ = bitmap;
505 void SetAllowableError(int amount) { allowable_error_ = amount; }
506 void SetExcludeRect(gfx::Rect exclude) { exclude_rect_ = exclude; }
508 GURL TestUrl() override { return GURL(test_url_); }
510 void SetTestUrl(std::string url) { test_url_ = url; }
512 // Loads a page two boxes side-by-side, each half the width of
513 // |html_rect_size|, and with different background colors. The test then
514 // copies from |copy_rect| region of the page into a bitmap of size
515 // |output_size|, and examines the resulting bitmap/VideoFrame.
516 // Note that |output_size| may not have the same size as |copy_rect| (e.g.
517 // when the output is scaled).
518 void PerformTestWithLeftRightRects(const gfx::Size& html_rect_size,
519 const gfx::Rect& copy_rect,
520 const gfx::Size& output_size,
522 const gfx::Size box_size(html_rect_size.width() / 2,
523 html_rect_size.height());
524 SetTestUrl(base::StringPrintf(
525 "data:text/html,<!doctype html>"
527 " <div class='right'></div>"
530 "body { padding: 0; margin: 0; }"
531 ".left { position: absolute;"
536 ".right { position: absolute;"
544 " domAutomationController.setAutomationId(0);"
545 " domAutomationController.send(\"DONE\");"
553 SET_UP_SURFACE_OR_PASS_TEST("\"DONE\"");
554 if (!ShouldContinueAfterTestURLLoad())
557 RenderWidgetHostViewBase* rwhvp = GetRenderWidgetHostView();
558 if (video_frame && !rwhvp->CanCopyToVideoFrame()) {
559 // This should only happen on Mac when using the software compositor.
560 // Otherwise, raise an error. This can be removed when Mac is moved to a
561 // browser compositor.
562 // http://crbug.com/314190
563 #if defined(OS_MACOSX)
564 if (!content::GpuDataManager::GetInstance()->GpuAccessAllowed(NULL)) {
565 LOG(WARNING) << ("Blindly passing this test because copying to "
566 "video frames is not supported on this platform.");
573 // The page is loaded in the renderer, wait for a new frame to arrive.
574 uint32 frame = rwhvp->RendererFrameNumber();
575 while (!GetRenderWidgetHost()->ScheduleComposite())
577 while (rwhvp->RendererFrameNumber() == frame)
580 SkBitmap expected_bitmap;
581 SetupLeftRightBitmap(output_size, &expected_bitmap);
582 SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap);
584 base::RunLoop run_loop;
586 // Allow pixel differences as long as we have the right idea.
587 SetAllowableError(0x10);
588 // Exclude the middle two columns which are blended between the two sides.
590 gfx::Rect(output_size.width() / 2 - 1, 0, 2, output_size.height()));
592 scoped_refptr<media::VideoFrame> video_frame =
593 media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
595 gfx::Rect(output_size),
599 base::Callback<void(bool success)> callback =
600 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
601 CopyFromCompositingSurfaceCallbackForVideo,
602 base::Unretained(this),
604 run_loop.QuitClosure());
605 rwhvp->CopyFromCompositingSurfaceToVideoFrame(copy_rect,
609 if (IsDelegatedRendererEnabled()) {
610 if (!content::GpuDataManager::GetInstance()
611 ->CanUseGpuBrowserCompositor()) {
612 // Skia rendering can cause color differences, particularly in the
613 // middle two columns.
614 SetAllowableError(2);
615 SetExcludeRect(gfx::Rect(
616 output_size.width() / 2 - 1, 0, 2, output_size.height()));
620 base::Callback<void(bool, const SkBitmap&)> callback =
621 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
622 CopyFromCompositingSurfaceCallback,
623 base::Unretained(this),
624 run_loop.QuitClosure());
625 rwhvp->CopyFromCompositingSurface(copy_rect,
633 // Sets up |bitmap| to have size |copy_size|. It floods the left half with
634 // #0ff and the right half with #ff0.
635 void SetupLeftRightBitmap(const gfx::Size& copy_size, SkBitmap* bitmap) {
636 bitmap->allocN32Pixels(copy_size.width(), copy_size.height());
637 // Left half is #0ff.
638 bitmap->eraseARGB(255, 0, 255, 255);
639 // Right half is #ff0.
641 SkAutoLockPixels lock(*bitmap);
642 for (int i = 0; i < copy_size.width() / 2; ++i) {
643 for (int j = 0; j < copy_size.height(); ++j) {
644 *(bitmap->getAddr32(copy_size.width() / 2 + i, j)) =
645 SkColorSetARGB(255, 255, 255, 0);
652 virtual bool ShouldContinueAfterTestURLLoad() {
657 bool expected_copy_from_compositing_surface_result_;
658 SkBitmap expected_copy_from_compositing_surface_bitmap_;
659 int allowable_error_;
660 gfx::Rect exclude_rect_;
661 std::string test_url_;
664 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
665 CopyFromCompositingSurface_Origin_Unscaled) {
666 gfx::Rect copy_rect(400, 300);
667 gfx::Size output_size = copy_rect.size();
668 gfx::Size html_rect_size(400, 300);
669 bool video_frame = false;
670 PerformTestWithLeftRightRects(html_rect_size,
676 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
677 CopyFromCompositingSurface_Origin_Scaled) {
678 gfx::Rect copy_rect(400, 300);
679 gfx::Size output_size(200, 100);
680 gfx::Size html_rect_size(400, 300);
681 bool video_frame = false;
682 PerformTestWithLeftRightRects(html_rect_size,
688 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
689 CopyFromCompositingSurface_Cropped_Unscaled) {
690 // Grab 60x60 pixels from the center of the tab contents.
691 gfx::Rect copy_rect(400, 300);
692 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
694 gfx::Size output_size = copy_rect.size();
695 gfx::Size html_rect_size(400, 300);
696 bool video_frame = false;
697 PerformTestWithLeftRightRects(html_rect_size,
703 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
704 CopyFromCompositingSurface_Cropped_Scaled) {
705 // Grab 60x60 pixels from the center of the tab contents.
706 gfx::Rect copy_rect(400, 300);
707 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
709 gfx::Size output_size(20, 10);
710 gfx::Size html_rect_size(400, 300);
711 bool video_frame = false;
712 PerformTestWithLeftRightRects(html_rect_size,
718 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
719 CopyFromCompositingSurface_ForVideoFrame) {
720 // Grab 90x60 pixels from the center of the tab contents.
721 gfx::Rect copy_rect(400, 300);
722 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(45, 30),
724 gfx::Size output_size = copy_rect.size();
725 gfx::Size html_rect_size(400, 300);
726 bool video_frame = true;
727 PerformTestWithLeftRightRects(html_rect_size,
733 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
734 CopyFromCompositingSurface_ForVideoFrame_Scaled) {
735 // Grab 90x60 pixels from the center of the tab contents.
736 gfx::Rect copy_rect(400, 300);
737 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(45, 30),
739 // Scale to 30 x 20 (preserve aspect ratio).
740 gfx::Size output_size(30, 20);
741 gfx::Size html_rect_size(400, 300);
742 bool video_frame = true;
743 PerformTestWithLeftRightRects(html_rect_size,
749 class CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
750 : public CompositingRenderWidgetHostViewBrowserTestTabCapture {
752 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI() {}
755 void SetUpCommandLine(base::CommandLine* cmd) override {
756 CompositingRenderWidgetHostViewBrowserTestTabCapture::SetUpCommandLine(cmd);
757 cmd->AppendSwitchASCII(switches::kForceDeviceScaleFactor,
758 base::StringPrintf("%f", scale()));
761 bool ShouldContinueAfterTestURLLoad() override {
762 // Short-circuit a pass for platforms where setting up high-DPI fails.
763 const float actual_scale_factor =
764 GetScaleFactorForView(GetRenderWidgetHostView());
765 if (actual_scale_factor != scale()) {
766 LOG(WARNING) << "Blindly passing this test; unable to force device scale "
767 << "factor: seems to be " << actual_scale_factor
768 << " but expected " << scale();
771 VLOG(1) << ("Successfully forced device scale factor. Moving forward with "
776 static float scale() { return 2.0f; }
779 DISALLOW_COPY_AND_ASSIGN(
780 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI);
783 // ImageSkia (related to ResourceBundle) implementation crashes the process on
784 // Windows when this content_browsertest forces a device scale factor.
785 // http://crbug.com/399349
787 // These tests are flaky on ChromeOS builders. See http://crbug.com/406018.
788 #if defined(OS_WIN) || defined(OS_CHROMEOS)
789 #define MAYBE_CopyToBitmap_EntireRegion DISABLED_CopyToBitmap_EntireRegion
790 #define MAYBE_CopyToBitmap_CenterRegion DISABLED_CopyToBitmap_CenterRegion
791 #define MAYBE_CopyToBitmap_ScaledResult DISABLED_CopyToBitmap_ScaledResult
792 #define MAYBE_CopyToVideoFrame_EntireRegion \
793 DISABLED_CopyToVideoFrame_EntireRegion
794 #define MAYBE_CopyToVideoFrame_CenterRegion \
795 DISABLED_CopyToVideoFrame_CenterRegion
796 #define MAYBE_CopyToVideoFrame_ScaledResult \
797 DISABLED_CopyToVideoFrame_ScaledResult
799 #define MAYBE_CopyToBitmap_EntireRegion CopyToBitmap_EntireRegion
800 #define MAYBE_CopyToBitmap_CenterRegion CopyToBitmap_CenterRegion
801 #define MAYBE_CopyToBitmap_ScaledResult CopyToBitmap_ScaledResult
802 #define MAYBE_CopyToVideoFrame_EntireRegion CopyToVideoFrame_EntireRegion
803 #define MAYBE_CopyToVideoFrame_CenterRegion CopyToVideoFrame_CenterRegion
804 #define MAYBE_CopyToVideoFrame_ScaledResult CopyToVideoFrame_ScaledResult
807 IN_PROC_BROWSER_TEST_P(
808 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
809 MAYBE_CopyToBitmap_EntireRegion) {
810 gfx::Size html_rect_size(200, 150);
811 gfx::Rect copy_rect(200, 150);
812 // Scale the output size so that, internally, scaling is not occurring.
813 gfx::Size output_size =
814 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
815 bool video_frame = false;
816 PerformTestWithLeftRightRects(html_rect_size,
822 IN_PROC_BROWSER_TEST_P(
823 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
824 MAYBE_CopyToBitmap_CenterRegion) {
825 gfx::Size html_rect_size(200, 150);
826 // Grab 90x60 pixels from the center of the tab contents.
827 gfx::Rect copy_rect =
828 gfx::Rect(gfx::Rect(html_rect_size).CenterPoint() - gfx::Vector2d(45, 30),
830 // Scale the output size so that, internally, scaling is not occurring.
831 gfx::Size output_size =
832 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
833 bool video_frame = false;
834 PerformTestWithLeftRightRects(html_rect_size,
840 IN_PROC_BROWSER_TEST_P(
841 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
842 MAYBE_CopyToBitmap_ScaledResult) {
843 gfx::Size html_rect_size(200, 100);
844 gfx::Rect copy_rect(200, 100);
845 // Output is being down-scaled since output_size is in phyiscal pixels.
846 gfx::Size output_size(200, 100);
847 bool video_frame = false;
848 PerformTestWithLeftRightRects(html_rect_size,
854 IN_PROC_BROWSER_TEST_P(
855 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
856 MAYBE_CopyToVideoFrame_EntireRegion) {
857 gfx::Size html_rect_size(200, 150);
858 gfx::Rect copy_rect(200, 150);
859 // Scale the output size so that, internally, scaling is not occurring.
860 gfx::Size output_size =
861 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
862 bool video_frame = true;
863 PerformTestWithLeftRightRects(html_rect_size,
869 IN_PROC_BROWSER_TEST_P(
870 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
871 MAYBE_CopyToVideoFrame_CenterRegion) {
872 gfx::Size html_rect_size(200, 150);
873 // Grab 90x60 pixels from the center of the tab contents.
874 gfx::Rect copy_rect =
875 gfx::Rect(gfx::Rect(html_rect_size).CenterPoint() - gfx::Vector2d(45, 30),
877 // Scale the output size so that, internally, scaling is not occurring.
878 gfx::Size output_size =
879 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
880 bool video_frame = true;
881 PerformTestWithLeftRightRects(html_rect_size,
887 IN_PROC_BROWSER_TEST_P(
888 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
889 MAYBE_CopyToVideoFrame_ScaledResult) {
890 gfx::Size html_rect_size(200, 100);
891 gfx::Rect copy_rect(200, 100);
892 // Output is being down-scaled since output_size is in phyiscal pixels.
893 gfx::Size output_size(200, 100);
894 bool video_frame = true;
895 PerformTestWithLeftRightRects(html_rect_size,
901 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
902 CompositingRenderWidgetHostViewBrowserTest,
903 testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
904 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
905 CompositingRenderWidgetHostViewBrowserTestTabCapture,
906 testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
907 INSTANTIATE_TEST_CASE_P(
908 GLAndSoftwareCompositing,
909 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
910 testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
912 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
915 } // namespace content