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/barrier_closure.h"
6 #include "base/command_line.h"
7 #include "base/message_loop/message_loop_proxy.h"
8 #include "base/path_service.h"
9 #include "base/run_loop.h"
10 #include "content/browser/gpu/compositor_util.h"
11 #include "content/browser/gpu/gpu_data_manager_impl.h"
12 #include "content/browser/renderer_host/dip_util.h"
13 #include "content/browser/renderer_host/render_widget_host_impl.h"
14 #include "content/browser/renderer_host/render_widget_host_view_base.h"
15 #include "content/public/browser/gpu_data_manager.h"
16 #include "content/public/browser/render_view_host.h"
17 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/common/content_paths.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/public/common/url_constants.h"
22 #include "content/public/test/browser_test_utils.h"
23 #include "content/public/test/content_browser_test.h"
24 #include "content/public/test/content_browser_test_utils.h"
25 #include "content/shell/browser/shell.h"
26 #include "media/base/video_frame.h"
27 #include "media/blink/skcanvas_video_renderer.h"
28 #include "net/base/filename_util.h"
29 #include "third_party/skia/include/core/SkBitmap.h"
30 #include "third_party/skia/include/core/SkCanvas.h"
31 #include "ui/base/layout.h"
32 #include "ui/base/ui_base_switches.h"
33 #include "ui/gfx/geometry/size_conversions.h"
34 #include "ui/gfx/switches.h"
35 #include "ui/gl/gl_switches.h"
38 #include "base/win/windows_version.h"
39 #include "ui/gfx/win/dpi.h"
45 // Convenience macro: Short-circuit a pass for the tests where platform support
46 // for forced-compositing mode (or disabled-compositing mode) is lacking.
47 #define SET_UP_SURFACE_OR_PASS_TEST(wait_message) \
48 if (!SetUpSourceSurface(wait_message)) { \
50 << ("Blindly passing this test: This platform does not support " \
51 "forced compositing (or forced-disabled compositing) mode."); \
55 // Common base class for browser tests. This is subclassed twice: Once to test
56 // the browser in forced-compositing mode, and once to test with compositing
58 class RenderWidgetHostViewBrowserTest
: public ContentBrowserTest
{
60 RenderWidgetHostViewBrowserTest()
61 : frame_size_(400, 300),
62 callback_invoke_count_(0),
63 frames_captured_(0) {}
65 void SetUpOnMainThread() override
{
66 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA
, &test_dir_
));
69 // Attempts to set up the source surface. Returns false if unsupported on the
71 virtual bool SetUpSourceSurface(const char* wait_message
) = 0;
73 int callback_invoke_count() const {
74 return callback_invoke_count_
;
77 int frames_captured() const {
78 return frames_captured_
;
81 const gfx::Size
& frame_size() const {
85 const base::FilePath
& test_dir() const {
89 RenderViewHost
* GetRenderViewHost() const {
90 RenderViewHost
* const rvh
= shell()->web_contents()->GetRenderViewHost();
95 RenderWidgetHostImpl
* GetRenderWidgetHost() const {
96 RenderWidgetHostImpl
* const rwh
= RenderWidgetHostImpl::From(
97 shell()->web_contents()->GetRenderWidgetHostView()->
98 GetRenderWidgetHost());
103 RenderWidgetHostViewBase
* GetRenderWidgetHostView() const {
104 return static_cast<RenderWidgetHostViewBase
*>(
105 GetRenderViewHost()->GetView());
108 // Callback when using CopyFromBackingStore() API.
109 void FinishCopyFromBackingStore(const base::Closure
& quit_closure
,
110 const SkBitmap
& bitmap
,
111 ReadbackResponse response
) {
112 ++callback_invoke_count_
;
113 if (response
== READBACK_SUCCESS
) {
115 EXPECT_FALSE(bitmap
.empty());
117 if (!quit_closure
.is_null())
121 // Callback when using CopyFromCompositingSurfaceToVideoFrame() API.
122 void FinishCopyFromCompositingSurface(const base::Closure
& quit_closure
,
123 bool frame_captured
) {
124 ++callback_invoke_count_
;
127 if (!quit_closure
.is_null())
131 // Callback when using frame subscriber API.
132 void FrameDelivered(const scoped_refptr
<base::MessageLoopProxy
>& loop
,
133 base::Closure quit_closure
,
134 base::TimeTicks timestamp
,
135 bool frame_captured
) {
136 ++callback_invoke_count_
;
139 if (!quit_closure
.is_null())
140 loop
->PostTask(FROM_HERE
, quit_closure
);
143 // Copy one frame using the CopyFromBackingStore API.
144 void RunBasicCopyFromBackingStoreTest() {
145 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
147 // Repeatedly call CopyFromBackingStore() since, on some platforms (e.g.,
148 // Windows), the operation will fail until the first "present" has been
150 int count_attempts
= 0;
153 base::RunLoop run_loop
;
154 GetRenderViewHost()->CopyFromBackingStore(
158 &RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore
,
159 base::Unretained(this),
160 run_loop
.QuitClosure()),
164 if (frames_captured())
170 EXPECT_EQ(count_attempts
, callback_invoke_count());
171 EXPECT_EQ(1, frames_captured());
175 // Waits until the source is available for copying.
176 void WaitForCopySourceReady() {
177 while (!GetRenderWidgetHostView()->IsSurfaceAvailableForCopy())
181 // Run the current message loop for a short time without unwinding the current
183 static void GiveItSomeTime() {
184 base::RunLoop run_loop
;
185 base::MessageLoop::current()->PostDelayedTask(
187 run_loop
.QuitClosure(),
188 base::TimeDelta::FromMilliseconds(10));
193 const gfx::Size frame_size_
;
194 base::FilePath test_dir_
;
195 int callback_invoke_count_
;
196 int frames_captured_
;
199 enum CompositingMode
{
201 SOFTWARE_COMPOSITING
,
204 class CompositingRenderWidgetHostViewBrowserTest
205 : public RenderWidgetHostViewBrowserTest
,
206 public testing::WithParamInterface
<CompositingMode
> {
208 explicit CompositingRenderWidgetHostViewBrowserTest()
209 : compositing_mode_(GetParam()) {}
211 void SetUp() override
{
212 if (compositing_mode_
== SOFTWARE_COMPOSITING
)
213 UseSoftwareCompositing();
214 RenderWidgetHostViewBrowserTest::SetUp();
217 virtual GURL
TestUrl() {
218 return net::FilePathToFileURL(
219 test_dir().AppendASCII("rwhv_compositing_animation.html"));
222 bool SetUpSourceSurface(const char* wait_message
) override
{
223 content::DOMMessageQueue message_queue
;
224 NavigateToURL(shell(), TestUrl());
225 if (wait_message
!= NULL
) {
226 std::string
result(wait_message
);
227 if (!message_queue
.WaitForMessage(&result
)) {
228 EXPECT_TRUE(false) << "WaitForMessage " << result
<< " failed.";
233 // A frame might not be available yet. So, wait for it.
234 WaitForCopySourceReady();
239 const CompositingMode compositing_mode_
;
241 DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewBrowserTest
);
244 class FakeFrameSubscriber
: public RenderWidgetHostViewFrameSubscriber
{
247 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback
)
248 : callback_(callback
) {
251 bool ShouldCaptureFrame(const gfx::Rect
& damage_rect
,
252 base::TimeTicks present_time
,
253 scoped_refptr
<media::VideoFrame
>* storage
,
254 DeliverFrameCallback
* callback
) override
{
255 // Only allow one frame capture to be made. Otherwise, the compositor could
256 // start multiple captures, unbounded, and eventually its own limiter logic
257 // will begin invoking |callback| with a |false| result. This flakes out
258 // the unit tests, since they receive a "failed" callback before the later
259 // "success" callbacks.
260 if (callback_
.is_null())
262 *storage
= media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
263 *callback
= callback_
;
269 DeliverFrameCallback callback_
;
272 // Disable tests for Android and IOS as these platforms have incomplete
274 #if !defined(OS_ANDROID) && !defined(OS_IOS)
276 // The CopyFromBackingStore() API should work on all platforms when compositing
278 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
,
279 CopyFromBackingStore
) {
280 RunBasicCopyFromBackingStoreTest();
283 // Tests that the callback passed to CopyFromBackingStore is always called,
284 // even when the RenderWidgetHost is deleting in the middle of an async copy.
285 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
,
286 CopyFromBackingStore_CallbackDespiteDelete
) {
287 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
289 base::RunLoop run_loop
;
290 GetRenderViewHost()->CopyFromBackingStore(
293 base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore
,
294 base::Unretained(this),
295 run_loop
.QuitClosure()),
299 EXPECT_EQ(1, callback_invoke_count());
302 // Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is
303 // always called, even when the RenderWidgetHost is deleting in the middle of
305 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
,
306 CopyFromCompositingSurface_CallbackDespiteDelete
) {
307 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
308 RenderWidgetHostViewBase
* const view
= GetRenderWidgetHostView();
309 if (!view
->CanCopyToVideoFrame()) {
311 ("Blindly passing this test: CopyFromCompositingSurfaceToVideoFrame() "
312 "not supported on this platform.");
316 base::RunLoop run_loop
;
317 scoped_refptr
<media::VideoFrame
> dest
=
318 media::VideoFrame::CreateBlackFrame(frame_size());
319 view
->CopyFromCompositingSurfaceToVideoFrame(
320 gfx::Rect(view
->GetViewBounds().size()), dest
, base::Bind(
321 &RenderWidgetHostViewBrowserTest::FinishCopyFromCompositingSurface
,
322 base::Unretained(this), run_loop
.QuitClosure()));
325 EXPECT_EQ(1, callback_invoke_count());
328 // Test basic frame subscription functionality. We subscribe, and then run
329 // until at least one DeliverFrameCallback has been invoked.
330 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
,
331 FrameSubscriberTest
) {
332 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
333 RenderWidgetHostViewBase
* const view
= GetRenderWidgetHostView();
334 if (!view
->CanSubscribeFrame()) {
335 LOG(WARNING
) << ("Blindly passing this test: Frame subscription not "
336 "supported on this platform.");
340 base::RunLoop run_loop
;
341 scoped_ptr
<RenderWidgetHostViewFrameSubscriber
> subscriber(
342 new FakeFrameSubscriber(
343 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered
,
344 base::Unretained(this),
345 base::MessageLoopProxy::current(),
346 run_loop
.QuitClosure())));
347 view
->BeginFrameSubscription(subscriber
.Pass());
349 view
->EndFrameSubscription();
351 EXPECT_LE(1, callback_invoke_count());
352 EXPECT_LE(1, frames_captured());
355 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest
, CopyTwice
) {
356 SET_UP_SURFACE_OR_PASS_TEST(NULL
);
357 RenderWidgetHostViewBase
* const view
= GetRenderWidgetHostView();
358 if (!view
->CanCopyToVideoFrame()) {
359 LOG(WARNING
) << ("Blindly passing this test: "
360 "CopyFromCompositingSurfaceToVideoFrame() not supported "
361 "on this platform.");
365 base::RunLoop run_loop
;
366 scoped_refptr
<media::VideoFrame
> first_output
=
367 media::VideoFrame::CreateBlackFrame(frame_size());
368 ASSERT_TRUE(first_output
.get());
369 scoped_refptr
<media::VideoFrame
> second_output
=
370 media::VideoFrame::CreateBlackFrame(frame_size());
371 ASSERT_TRUE(second_output
.get());
372 base::Closure closure
= base::BarrierClosure(2, run_loop
.QuitClosure());
373 view
->CopyFromCompositingSurfaceToVideoFrame(
374 gfx::Rect(view
->GetViewBounds().size()), first_output
,
375 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered
,
376 base::Unretained(this), base::MessageLoopProxy::current(),
377 closure
, base::TimeTicks::Now()));
378 view
->CopyFromCompositingSurfaceToVideoFrame(
379 gfx::Rect(view
->GetViewBounds().size()), second_output
,
380 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered
,
381 base::Unretained(this), base::MessageLoopProxy::current(),
382 closure
, base::TimeTicks::Now()));
385 EXPECT_EQ(2, callback_invoke_count());
386 EXPECT_EQ(2, frames_captured());
389 class CompositingRenderWidgetHostViewBrowserTestTabCapture
390 : public CompositingRenderWidgetHostViewBrowserTest
{
392 CompositingRenderWidgetHostViewBrowserTestTabCapture()
393 : readback_response_(READBACK_NO_RESPONSE
),
395 test_url_("data:text/html,<!doctype html>") {}
397 void SetUp() override
{
399 CompositingRenderWidgetHostViewBrowserTest::SetUp();
402 void ReadbackRequestCallbackTest(base::Closure quit_callback
,
403 const SkBitmap
& bitmap
,
404 ReadbackResponse response
) {
405 readback_response_
= response
;
406 if (response
!= READBACK_SUCCESS
) {
411 SkAutoLockPixels
bitmap_lock(bitmap
);
413 // Check that the |bitmap| contains cyan and/or yellow pixels. This is
414 // needed because the compositor will read back "blank" frames until the
415 // first frame from the renderer is composited. See comments in
416 // PerformTestWithLeftRightRects() for more details about eliminating test
418 bool contains_a_test_color
= false;
419 for (int i
= 0; i
< bitmap
.width(); ++i
) {
420 for (int j
= 0; j
< bitmap
.height(); ++j
) {
421 if (!exclude_rect_
.IsEmpty() && exclude_rect_
.Contains(i
, j
))
424 const unsigned high_threshold
= 0xff - allowable_error_
;
425 const unsigned low_threshold
= 0x00 + allowable_error_
;
426 const SkColor color
= bitmap
.getColor(i
, j
);
427 const bool is_cyan
= SkColorGetR(color
) <= low_threshold
&&
428 SkColorGetG(color
) >= high_threshold
&&
429 SkColorGetB(color
) >= high_threshold
;
430 const bool is_yellow
= SkColorGetR(color
) >= high_threshold
&&
431 SkColorGetG(color
) >= high_threshold
&&
432 SkColorGetB(color
) <= low_threshold
;
433 if (is_cyan
|| is_yellow
) {
434 contains_a_test_color
= true;
439 if (!contains_a_test_color
) {
440 readback_response_
= READBACK_NO_TEST_COLORS
;
445 // Compare the readback |bitmap| to the |expected_bitmap|, pixel-by-pixel.
446 const SkBitmap
& expected_bitmap
=
447 expected_copy_from_compositing_surface_bitmap_
;
448 EXPECT_EQ(expected_bitmap
.width(), bitmap
.width());
449 EXPECT_EQ(expected_bitmap
.height(), bitmap
.height());
450 EXPECT_EQ(expected_bitmap
.colorType(), bitmap
.colorType());
451 SkAutoLockPixels
expected_bitmap_lock(expected_bitmap
);
453 for (int i
= 0; i
< bitmap
.width() && fails
< 10; ++i
) {
454 for (int j
= 0; j
< bitmap
.height() && fails
< 10; ++j
) {
455 if (!exclude_rect_
.IsEmpty() && exclude_rect_
.Contains(i
, j
))
458 SkColor expected_color
= expected_bitmap
.getColor(i
, j
);
459 SkColor color
= bitmap
.getColor(i
, j
);
460 int expected_alpha
= SkColorGetA(expected_color
);
461 int alpha
= SkColorGetA(color
);
462 int expected_red
= SkColorGetR(expected_color
);
463 int red
= SkColorGetR(color
);
464 int expected_green
= SkColorGetG(expected_color
);
465 int green
= SkColorGetG(color
);
466 int expected_blue
= SkColorGetB(expected_color
);
467 int blue
= SkColorGetB(color
);
468 EXPECT_NEAR(expected_alpha
, alpha
, allowable_error_
)
469 << "expected_color: " << std::hex
<< expected_color
470 << " color: " << color
471 << " Failed at " << std::dec
<< i
<< ", " << j
472 << " Failure " << ++fails
;
473 EXPECT_NEAR(expected_red
, red
, allowable_error_
)
474 << "expected_color: " << std::hex
<< expected_color
475 << " color: " << color
476 << " Failed at " << std::dec
<< i
<< ", " << j
477 << " Failure " << ++fails
;
478 EXPECT_NEAR(expected_green
, green
, allowable_error_
)
479 << "expected_color: " << std::hex
<< expected_color
480 << " color: " << color
481 << " Failed at " << std::dec
<< i
<< ", " << j
482 << " Failure " << ++fails
;
483 EXPECT_NEAR(expected_blue
, blue
, allowable_error_
)
484 << "expected_color: " << std::hex
<< expected_color
485 << " color: " << color
486 << " Failed at " << std::dec
<< i
<< ", " << j
487 << " Failure " << ++fails
;
490 EXPECT_LT(fails
, 10);
495 void ReadbackRequestCallbackForVideo(
496 scoped_refptr
<media::VideoFrame
> video_frame
,
497 base::Closure quit_callback
,
500 readback_response_
= READBACK_TO_VIDEO_FRAME_FAILED
;
505 media::SkCanvasVideoRenderer video_renderer
;
508 bitmap
.allocN32Pixels(video_frame
->visible_rect().width(),
509 video_frame
->visible_rect().height());
510 // Don't clear the canvas because drawing a video frame by Src mode.
511 SkCanvas
canvas(bitmap
);
512 video_renderer
.Copy(video_frame
, &canvas
, media::Context3D());
514 ReadbackRequestCallbackTest(quit_callback
, bitmap
, READBACK_SUCCESS
);
517 void SetAllowableError(int amount
) { allowable_error_
= amount
; }
518 void SetExcludeRect(gfx::Rect exclude
) { exclude_rect_
= exclude
; }
520 GURL
TestUrl() override
{ return GURL(test_url_
); }
522 void SetTestUrl(std::string url
) { test_url_
= url
; }
524 // Loads a page two boxes side-by-side, each half the width of
525 // |html_rect_size|, and with different background colors. The test then
526 // copies from |copy_rect| region of the page into a bitmap of size
527 // |output_size|, and examines the resulting bitmap/VideoFrame.
528 // Note that |output_size| may not have the same size as |copy_rect| (e.g.
529 // when the output is scaled).
530 void PerformTestWithLeftRightRects(const gfx::Size
& html_rect_size
,
531 const gfx::Rect
& copy_rect
,
532 const gfx::Size
& output_size
,
534 const gfx::Size
box_size(html_rect_size
.width() / 2,
535 html_rect_size
.height());
536 SetTestUrl(base::StringPrintf(
537 "data:text/html,<!doctype html>"
539 " <div class='right'></div>"
542 "body { padding: 0; margin: 0; }"
543 ".left { position: absolute;"
548 ".right { position: absolute;"
556 " domAutomationController.setAutomationId(0);"
557 " domAutomationController.send(\"DONE\");"
565 SET_UP_SURFACE_OR_PASS_TEST("\"DONE\"");
566 if (!ShouldContinueAfterTestURLLoad())
569 RenderWidgetHostViewBase
* rwhv
= GetRenderWidgetHostView();
570 ASSERT_TRUE(!video_frame
|| rwhv
->CanCopyToVideoFrame());
572 SetupLeftRightBitmap(output_size
,
573 &expected_copy_from_compositing_surface_bitmap_
);
575 // The page is loaded in the renderer. Request frames from the renderer
576 // until readback succeeds. When readback succeeds, the resulting
577 // SkBitmap/VideoFrame is examined to ensure it matches the expected result.
578 // This loop is needed because:
579 // 1. Painting/Compositing is not synchronous with the Javascript engine,
580 // and so the "DONE" signal above could be received before the renderer
581 // provides a frame with the expected content. http://crbug.com/405282
582 // 2. Avoiding test flakiness: On some platforms, the readback operation
583 // is allowed to transiently fail. The purpose of these tests is to
584 // confirm correct cropping/scaling behavior; and not that every
585 // readback must succeed. http://crbug.com/444237
586 uint32 last_frame_number
= 0;
588 // Wait for renderer to provide the next frame.
589 while (!GetRenderWidgetHost()->ScheduleComposite())
591 while (rwhv
->RendererFrameNumber() == last_frame_number
)
593 last_frame_number
= rwhv
->RendererFrameNumber();
595 // Request readback. The callbacks will examine the pixels in the
596 // SkBitmap/VideoFrame result if readback was successful.
597 readback_response_
= READBACK_NO_RESPONSE
;
598 base::RunLoop run_loop
;
600 // Allow pixel differences as long as we have the right idea.
601 SetAllowableError(0x10);
602 // Exclude the middle two columns which are blended between the two
605 gfx::Rect(output_size
.width() / 2 - 1, 0, 2, output_size
.height()));
607 scoped_refptr
<media::VideoFrame
> video_frame
=
608 media::VideoFrame::CreateFrame(media::VideoFrame::YV12
,
610 gfx::Rect(output_size
),
614 base::Callback
<void(bool success
)> callback
=
615 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
616 ReadbackRequestCallbackForVideo
,
617 base::Unretained(this),
619 run_loop
.QuitClosure());
620 rwhv
->CopyFromCompositingSurfaceToVideoFrame(
621 copy_rect
, video_frame
, callback
);
623 if (IsDelegatedRendererEnabled()) {
624 if (!content::GpuDataManager::GetInstance()
625 ->CanUseGpuBrowserCompositor()) {
626 // Skia rendering can cause color differences, particularly in the
627 // middle two columns.
628 SetAllowableError(2);
629 SetExcludeRect(gfx::Rect(
630 output_size
.width() / 2 - 1, 0, 2, output_size
.height()));
634 ReadbackRequestCallback callback
=
635 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
636 ReadbackRequestCallbackTest
,
637 base::Unretained(this),
638 run_loop
.QuitClosure());
639 rwhv
->CopyFromCompositingSurface(
640 copy_rect
, output_size
, callback
, kN32_SkColorType
);
644 // If the readback operation did not provide a frame, log the reason
645 // to aid in future debugging. This information will also help determine
646 // whether the implementation is broken, or a test bot is in a bad state.
647 #define CASE_LOG_READBACK_WARNING(enum_value) \
649 LOG(WARNING) << "Readback attempt failed (render frame #" \
650 << last_frame_number << "). Reason: " #enum_value; \
652 switch (readback_response_
) {
653 case READBACK_SUCCESS
:
655 CASE_LOG_READBACK_WARNING(READBACK_FAILED
);
656 CASE_LOG_READBACK_WARNING(READBACK_FORMAT_NOT_SUPPORTED
);
657 CASE_LOG_READBACK_WARNING(READBACK_NOT_SUPPORTED
);
658 CASE_LOG_READBACK_WARNING(READBACK_SURFACE_UNAVAILABLE
);
659 CASE_LOG_READBACK_WARNING(READBACK_MEMORY_ALLOCATION_FAILURE
);
660 CASE_LOG_READBACK_WARNING(READBACK_NO_TEST_COLORS
);
661 CASE_LOG_READBACK_WARNING(READBACK_TO_VIDEO_FRAME_FAILED
);
664 << "Invalid readback response value: " << readback_response_
;
667 } while (readback_response_
!= READBACK_SUCCESS
);
670 // Sets up |bitmap| to have size |copy_size|. It floods the left half with
671 // #0ff and the right half with #ff0.
672 void SetupLeftRightBitmap(const gfx::Size
& copy_size
, SkBitmap
* bitmap
) {
673 bitmap
->allocN32Pixels(copy_size
.width(), copy_size
.height());
674 // Left half is #0ff.
675 bitmap
->eraseARGB(255, 0, 255, 255);
676 // Right half is #ff0.
678 SkAutoLockPixels
lock(*bitmap
);
679 for (int i
= 0; i
< copy_size
.width() / 2; ++i
) {
680 for (int j
= 0; j
< copy_size
.height(); ++j
) {
681 *(bitmap
->getAddr32(copy_size
.width() / 2 + i
, j
)) =
682 SkColorSetARGB(255, 255, 255, 0);
689 // Additional ReadbackResponse enum values only used within this test module,
690 // to distinguish readback exception cases further.
691 enum ExtraReadbackResponsesForTest
{
692 READBACK_NO_RESPONSE
= -1337,
693 READBACK_NO_TEST_COLORS
,
694 READBACK_TO_VIDEO_FRAME_FAILED
,
697 virtual bool ShouldContinueAfterTestURLLoad() {
702 // |readback_response_| is always a content::ReadbackResponse or
703 // ExtraReadbackResponsesForTest enum value.
704 int readback_response_
;
705 SkBitmap expected_copy_from_compositing_surface_bitmap_
;
706 int allowable_error_
;
707 gfx::Rect exclude_rect_
;
708 std::string test_url_
;
711 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
712 CopyFromCompositingSurface_Origin_Unscaled
) {
713 gfx::Rect
copy_rect(400, 300);
714 gfx::Size output_size
= copy_rect
.size();
715 gfx::Size
html_rect_size(400, 300);
716 bool video_frame
= false;
717 PerformTestWithLeftRightRects(html_rect_size
,
723 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
724 CopyFromCompositingSurface_Origin_Scaled
) {
725 gfx::Rect
copy_rect(400, 300);
726 gfx::Size
output_size(200, 100);
727 gfx::Size
html_rect_size(400, 300);
728 bool video_frame
= false;
729 PerformTestWithLeftRightRects(html_rect_size
,
735 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
736 CopyFromCompositingSurface_Cropped_Unscaled
) {
737 // Grab 60x60 pixels from the center of the tab contents.
738 gfx::Rect
copy_rect(400, 300);
739 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(30, 30),
741 gfx::Size output_size
= copy_rect
.size();
742 gfx::Size
html_rect_size(400, 300);
743 bool video_frame
= false;
744 PerformTestWithLeftRightRects(html_rect_size
,
750 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
751 CopyFromCompositingSurface_Cropped_Scaled
) {
752 // Grab 60x60 pixels from the center of the tab contents.
753 gfx::Rect
copy_rect(400, 300);
754 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(30, 30),
756 gfx::Size
output_size(20, 10);
757 gfx::Size
html_rect_size(400, 300);
758 bool video_frame
= false;
759 PerformTestWithLeftRightRects(html_rect_size
,
765 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
766 CopyFromCompositingSurface_ForVideoFrame
) {
767 // Grab 90x60 pixels from the center of the tab contents.
768 gfx::Rect
copy_rect(400, 300);
769 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(45, 30),
771 gfx::Size output_size
= copy_rect
.size();
772 gfx::Size
html_rect_size(400, 300);
773 bool video_frame
= true;
774 PerformTestWithLeftRightRects(html_rect_size
,
780 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture
,
781 CopyFromCompositingSurface_ForVideoFrame_Scaled
) {
782 // Grab 90x60 pixels from the center of the tab contents.
783 gfx::Rect
copy_rect(400, 300);
784 copy_rect
= gfx::Rect(copy_rect
.CenterPoint() - gfx::Vector2d(45, 30),
786 // Scale to 30 x 20 (preserve aspect ratio).
787 gfx::Size
output_size(30, 20);
788 gfx::Size
html_rect_size(400, 300);
789 bool video_frame
= true;
790 PerformTestWithLeftRightRects(html_rect_size
,
796 class CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
797 : public CompositingRenderWidgetHostViewBrowserTestTabCapture
{
799 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI() {}
802 void SetUpCommandLine(base::CommandLine
* cmd
) override
{
803 CompositingRenderWidgetHostViewBrowserTestTabCapture::SetUpCommandLine(cmd
);
804 cmd
->AppendSwitchASCII(switches::kForceDeviceScaleFactor
,
805 base::StringPrintf("%f", scale()));
808 bool ShouldContinueAfterTestURLLoad() override
{
809 // Short-circuit a pass for platforms where setting up high-DPI fails.
810 const float actual_scale_factor
=
811 GetScaleFactorForView(GetRenderWidgetHostView());
812 if (actual_scale_factor
!= scale()) {
813 LOG(WARNING
) << "Blindly passing this test; unable to force device scale "
814 << "factor: seems to be " << actual_scale_factor
815 << " but expected " << scale();
818 VLOG(1) << ("Successfully forced device scale factor. Moving forward with "
823 static float scale() { return 2.0f
; }
826 DISALLOW_COPY_AND_ASSIGN(
827 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
);
830 // NineImagePainter implementation crashes the process on Windows when this
831 // content_browsertest forces a device scale factor. http://crbug.com/399349
833 #define MAYBE_CopyToBitmap_EntireRegion DISABLED_CopyToBitmap_EntireRegion
834 #define MAYBE_CopyToBitmap_CenterRegion DISABLED_CopyToBitmap_CenterRegion
835 #define MAYBE_CopyToBitmap_ScaledResult DISABLED_CopyToBitmap_ScaledResult
836 #define MAYBE_CopyToVideoFrame_EntireRegion \
837 DISABLED_CopyToVideoFrame_EntireRegion
838 #define MAYBE_CopyToVideoFrame_CenterRegion \
839 DISABLED_CopyToVideoFrame_CenterRegion
840 #define MAYBE_CopyToVideoFrame_ScaledResult \
841 DISABLED_CopyToVideoFrame_ScaledResult
843 #define MAYBE_CopyToBitmap_EntireRegion CopyToBitmap_EntireRegion
844 #define MAYBE_CopyToBitmap_CenterRegion CopyToBitmap_CenterRegion
845 #define MAYBE_CopyToBitmap_ScaledResult CopyToBitmap_ScaledResult
846 #define MAYBE_CopyToVideoFrame_EntireRegion CopyToVideoFrame_EntireRegion
847 #define MAYBE_CopyToVideoFrame_CenterRegion CopyToVideoFrame_CenterRegion
848 #define MAYBE_CopyToVideoFrame_ScaledResult CopyToVideoFrame_ScaledResult
851 IN_PROC_BROWSER_TEST_P(
852 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
,
853 MAYBE_CopyToBitmap_EntireRegion
) {
854 gfx::Size
html_rect_size(200, 150);
855 gfx::Rect
copy_rect(200, 150);
856 // Scale the output size so that, internally, scaling is not occurring.
857 gfx::Size output_size
=
858 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect
.size(), scale()));
859 bool video_frame
= false;
860 PerformTestWithLeftRightRects(html_rect_size
,
866 IN_PROC_BROWSER_TEST_P(
867 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
,
868 MAYBE_CopyToBitmap_CenterRegion
) {
869 gfx::Size
html_rect_size(200, 150);
870 // Grab 90x60 pixels from the center of the tab contents.
871 gfx::Rect copy_rect
=
872 gfx::Rect(gfx::Rect(html_rect_size
).CenterPoint() - gfx::Vector2d(45, 30),
874 // Scale the output size so that, internally, scaling is not occurring.
875 gfx::Size output_size
=
876 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect
.size(), scale()));
877 bool video_frame
= false;
878 PerformTestWithLeftRightRects(html_rect_size
,
884 IN_PROC_BROWSER_TEST_P(
885 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
,
886 MAYBE_CopyToBitmap_ScaledResult
) {
887 gfx::Size
html_rect_size(200, 100);
888 gfx::Rect
copy_rect(200, 100);
889 // Output is being down-scaled since output_size is in phyiscal pixels.
890 gfx::Size
output_size(200, 100);
891 bool video_frame
= false;
892 PerformTestWithLeftRightRects(html_rect_size
,
898 IN_PROC_BROWSER_TEST_P(
899 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
,
900 MAYBE_CopyToVideoFrame_EntireRegion
) {
901 gfx::Size
html_rect_size(200, 150);
902 gfx::Rect
copy_rect(200, 150);
903 // Scale the output size so that, internally, scaling is not occurring.
904 gfx::Size output_size
=
905 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect
.size(), scale()));
906 bool video_frame
= true;
907 PerformTestWithLeftRightRects(html_rect_size
,
913 IN_PROC_BROWSER_TEST_P(
914 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
,
915 MAYBE_CopyToVideoFrame_CenterRegion
) {
916 gfx::Size
html_rect_size(200, 150);
917 // Grab 90x60 pixels from the center of the tab contents.
918 gfx::Rect copy_rect
=
919 gfx::Rect(gfx::Rect(html_rect_size
).CenterPoint() - gfx::Vector2d(45, 30),
921 // Scale the output size so that, internally, scaling is not occurring.
922 gfx::Size output_size
=
923 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect
.size(), scale()));
924 bool video_frame
= true;
925 PerformTestWithLeftRightRects(html_rect_size
,
931 IN_PROC_BROWSER_TEST_P(
932 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
,
933 MAYBE_CopyToVideoFrame_ScaledResult
) {
934 gfx::Size
html_rect_size(200, 100);
935 gfx::Rect
copy_rect(200, 100);
936 // Output is being down-scaled since output_size is in phyiscal pixels.
937 gfx::Size
output_size(200, 100);
938 bool video_frame
= true;
939 PerformTestWithLeftRightRects(html_rect_size
,
945 #if defined(OS_CHROMEOS)
946 // On ChromeOS there is no software compositing.
947 static const auto kTestCompositingModes
= testing::Values(GL_COMPOSITING
);
949 static const auto kTestCompositingModes
=
950 testing::Values(GL_COMPOSITING
, SOFTWARE_COMPOSITING
);
953 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing
,
954 CompositingRenderWidgetHostViewBrowserTest
,
955 kTestCompositingModes
);
956 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing
,
957 CompositingRenderWidgetHostViewBrowserTestTabCapture
,
958 kTestCompositingModes
);
959 INSTANTIATE_TEST_CASE_P(
960 GLAndSoftwareCompositing
,
961 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
,
962 kTestCompositingModes
);
964 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
967 } // namespace content