Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_browsertest.cc
blob88da5a7a38a4617568bb3950901c814e7fc9c26f
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"
36 #if defined(OS_WIN)
37 #include "base/win/windows_version.h"
38 #include "ui/gfx/win/dpi.h"
39 #endif
41 namespace content {
42 namespace {
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)) { \
48 LOG(WARNING) \
49 << ("Blindly passing this test: This platform does not support " \
50 "forced compositing (or forced-disabled compositing) mode."); \
51 return; \
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
56 // mode disabled.
57 class RenderWidgetHostViewBrowserTest : public ContentBrowserTest {
58 public:
59 RenderWidgetHostViewBrowserTest()
60 : frame_size_(400, 300),
61 callback_invoke_count_(0),
62 frames_captured_(0) {}
64 virtual 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
69 // current platform.
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 {
81 return frame_size_;
84 const base::FilePath& test_dir() const {
85 return test_dir_;
88 RenderViewHost* GetRenderViewHost() const {
89 RenderViewHost* const rvh = shell()->web_contents()->GetRenderViewHost();
90 CHECK(rvh);
91 return rvh;
94 RenderWidgetHostImpl* GetRenderWidgetHost() const {
95 RenderWidgetHostImpl* const rwh = RenderWidgetHostImpl::From(
96 shell()->web_contents()->GetRenderWidgetHostView()->
97 GetRenderWidgetHost());
98 CHECK(rwh);
99 return rwh;
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,
109 bool frame_captured,
110 const SkBitmap& bitmap) {
111 ++callback_invoke_count_;
112 if (frame_captured) {
113 ++frames_captured_;
114 EXPECT_FALSE(bitmap.empty());
116 if (!quit_closure.is_null())
117 quit_closure.Run();
120 // Callback when using CopyFromCompositingSurfaceToVideoFrame() API.
121 void FinishCopyFromCompositingSurface(const base::Closure& quit_closure,
122 bool frame_captured) {
123 ++callback_invoke_count_;
124 if (frame_captured)
125 ++frames_captured_;
126 if (!quit_closure.is_null())
127 quit_closure.Run();
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_;
136 if (frame_captured)
137 ++frames_captured_;
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
148 // made.
149 int count_attempts = 0;
150 while (true) {
151 ++count_attempts;
152 base::RunLoop run_loop;
153 GetRenderViewHost()->CopyFromBackingStore(
154 gfx::Rect(),
155 frame_size(),
156 base::Bind(
157 &RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
158 base::Unretained(this),
159 run_loop.QuitClosure()),
160 kN32_SkColorType);
161 run_loop.Run();
163 if (frames_captured())
164 break;
165 else
166 GiveItSomeTime();
169 EXPECT_EQ(count_attempts, callback_invoke_count());
170 EXPECT_EQ(1, frames_captured());
173 protected:
174 // Waits until the source is available for copying.
175 void WaitForCopySourceReady() {
176 while (!GetRenderWidgetHostView()->IsSurfaceAvailableForCopy())
177 GiveItSomeTime();
180 // Run the current message loop for a short time without unwinding the current
181 // call stack.
182 static void GiveItSomeTime() {
183 base::RunLoop run_loop;
184 base::MessageLoop::current()->PostDelayedTask(
185 FROM_HERE,
186 run_loop.QuitClosure(),
187 base::TimeDelta::FromMilliseconds(10));
188 run_loop.Run();
191 private:
192 const gfx::Size frame_size_;
193 base::FilePath test_dir_;
194 int callback_invoke_count_;
195 int frames_captured_;
198 enum CompositingMode {
199 GL_COMPOSITING,
200 SOFTWARE_COMPOSITING,
203 class CompositingRenderWidgetHostViewBrowserTest
204 : public RenderWidgetHostViewBrowserTest,
205 public testing::WithParamInterface<CompositingMode> {
206 public:
207 explicit CompositingRenderWidgetHostViewBrowserTest()
208 : compositing_mode_(GetParam()) {}
210 virtual 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 virtual 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.";
228 return false;
232 // A frame might not be available yet. So, wait for it.
233 WaitForCopySourceReady();
234 return true;
237 private:
238 const CompositingMode compositing_mode_;
240 DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewBrowserTest);
243 class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
244 public:
245 FakeFrameSubscriber(
246 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback)
247 : callback_(callback) {
250 virtual 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())
260 return false;
261 *storage = media::VideoFrame::CreateBlackFrame(gfx::Size(100, 100));
262 *callback = callback_;
263 callback_.Reset();
264 return true;
267 private:
268 DeliverFrameCallback callback_;
271 // Disable tests for Android and IOS as these platforms have incomplete
272 // implementation.
273 #if !defined(OS_ANDROID) && !defined(OS_IOS)
275 // The CopyFromBackingStore() API should work on all platforms when compositing
276 // is enabled.
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(
290 gfx::Rect(),
291 frame_size(),
292 base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
293 base::Unretained(this),
294 run_loop.QuitClosure()),
295 kN32_SkColorType);
296 // Delete the surface before the callback is run.
297 GetRenderWidgetHostView()->AcceleratedSurfaceRelease();
298 run_loop.Run();
300 EXPECT_EQ(1, callback_invoke_count());
303 // Tests that the callback passed to CopyFromCompositingSurfaceToVideoFrame is
304 // always called, even when the RenderWidgetHost is deleting in the middle of
305 // an async copy.
307 // Test is flaky on Win. http://crbug.com/276783
308 #if defined(OS_WIN) || (defined(OS_CHROMEOS) && !defined(NDEBUG))
309 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
310 DISABLED_CopyFromCompositingSurface_CallbackDespiteDelete
311 #else
312 #define MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete \
313 CopyFromCompositingSurface_CallbackDespiteDelete
314 #endif
315 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
316 MAYBE_CopyFromCompositingSurface_CallbackDespiteDelete) {
317 SET_UP_SURFACE_OR_PASS_TEST(NULL);
318 RenderWidgetHostViewBase* const view = GetRenderWidgetHostView();
319 if (!view->CanCopyToVideoFrame()) {
320 LOG(WARNING) <<
321 ("Blindly passing this test: CopyFromCompositingSurfaceToVideoFrame() "
322 "not supported on this platform.");
323 return;
326 base::RunLoop run_loop;
327 scoped_refptr<media::VideoFrame> dest =
328 media::VideoFrame::CreateBlackFrame(frame_size());
329 view->CopyFromCompositingSurfaceToVideoFrame(
330 gfx::Rect(view->GetViewBounds().size()), dest, base::Bind(
331 &RenderWidgetHostViewBrowserTest::FinishCopyFromCompositingSurface,
332 base::Unretained(this), run_loop.QuitClosure()));
333 // Delete the surface before the callback is run.
334 view->AcceleratedSurfaceRelease();
335 run_loop.Run();
337 EXPECT_EQ(1, callback_invoke_count());
340 // Test basic frame subscription functionality. We subscribe, and then run
341 // until at least one DeliverFrameCallback has been invoked.
342 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
343 FrameSubscriberTest) {
344 SET_UP_SURFACE_OR_PASS_TEST(NULL);
345 RenderWidgetHostViewBase* const view = GetRenderWidgetHostView();
346 if (!view->CanSubscribeFrame()) {
347 LOG(WARNING) << ("Blindly passing this test: Frame subscription not "
348 "supported on this platform.");
349 return;
352 base::RunLoop run_loop;
353 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
354 new FakeFrameSubscriber(
355 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
356 base::Unretained(this),
357 base::MessageLoopProxy::current(),
358 run_loop.QuitClosure())));
359 view->BeginFrameSubscription(subscriber.Pass());
360 run_loop.Run();
361 view->EndFrameSubscription();
363 EXPECT_LE(1, callback_invoke_count());
364 EXPECT_LE(1, frames_captured());
367 // Test that we can copy twice from an accelerated composited page.
368 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest, CopyTwice) {
369 SET_UP_SURFACE_OR_PASS_TEST(NULL);
370 RenderWidgetHostViewBase* const view = GetRenderWidgetHostView();
371 if (!view->CanCopyToVideoFrame()) {
372 LOG(WARNING) << ("Blindly passing this test: "
373 "CopyFromCompositingSurfaceToVideoFrame() not supported "
374 "on this platform.");
375 return;
378 base::RunLoop run_loop;
379 scoped_refptr<media::VideoFrame> first_output =
380 media::VideoFrame::CreateBlackFrame(frame_size());
381 ASSERT_TRUE(first_output.get());
382 scoped_refptr<media::VideoFrame> second_output =
383 media::VideoFrame::CreateBlackFrame(frame_size());
384 ASSERT_TRUE(second_output.get());
385 view->CopyFromCompositingSurfaceToVideoFrame(
386 gfx::Rect(view->GetViewBounds().size()),
387 first_output,
388 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
389 base::Unretained(this),
390 base::MessageLoopProxy::current(),
391 base::Closure(),
392 base::TimeTicks::Now()));
393 view->CopyFromCompositingSurfaceToVideoFrame(
394 gfx::Rect(view->GetViewBounds().size()),
395 second_output,
396 base::Bind(&RenderWidgetHostViewBrowserTest::FrameDelivered,
397 base::Unretained(this),
398 base::MessageLoopProxy::current(),
399 run_loop.QuitClosure(),
400 base::TimeTicks::Now()));
401 run_loop.Run();
403 EXPECT_EQ(2, callback_invoke_count());
404 EXPECT_EQ(2, frames_captured());
407 class CompositingRenderWidgetHostViewBrowserTestTabCapture
408 : public CompositingRenderWidgetHostViewBrowserTest {
409 public:
410 CompositingRenderWidgetHostViewBrowserTestTabCapture()
411 : expected_copy_from_compositing_surface_result_(false),
412 allowable_error_(0),
413 test_url_("data:text/html,<!doctype html>") {}
415 virtual void SetUp() OVERRIDE {
416 EnablePixelOutput();
417 CompositingRenderWidgetHostViewBrowserTest::SetUp();
420 void CopyFromCompositingSurfaceCallback(base::Closure quit_callback,
421 bool result,
422 const SkBitmap& bitmap) {
423 EXPECT_EQ(expected_copy_from_compositing_surface_result_, result);
424 if (!result) {
425 quit_callback.Run();
426 return;
429 const SkBitmap& expected_bitmap =
430 expected_copy_from_compositing_surface_bitmap_;
431 EXPECT_EQ(expected_bitmap.width(), bitmap.width());
432 EXPECT_EQ(expected_bitmap.height(), bitmap.height());
433 EXPECT_EQ(expected_bitmap.colorType(), bitmap.colorType());
434 SkAutoLockPixels expected_bitmap_lock(expected_bitmap);
435 SkAutoLockPixels bitmap_lock(bitmap);
436 int fails = 0;
437 for (int i = 0; i < bitmap.width() && fails < 10; ++i) {
438 for (int j = 0; j < bitmap.height() && fails < 10; ++j) {
439 if (!exclude_rect_.IsEmpty() && exclude_rect_.Contains(i, j))
440 continue;
442 SkColor expected_color = expected_bitmap.getColor(i, j);
443 SkColor color = bitmap.getColor(i, j);
444 int expected_alpha = SkColorGetA(expected_color);
445 int alpha = SkColorGetA(color);
446 int expected_red = SkColorGetR(expected_color);
447 int red = SkColorGetR(color);
448 int expected_green = SkColorGetG(expected_color);
449 int green = SkColorGetG(color);
450 int expected_blue = SkColorGetB(expected_color);
451 int blue = SkColorGetB(color);
452 EXPECT_NEAR(expected_alpha, alpha, allowable_error_)
453 << "expected_color: " << std::hex << expected_color
454 << " color: " << color
455 << " Failed at " << std::dec << i << ", " << j
456 << " Failure " << ++fails;
457 EXPECT_NEAR(expected_red, red, allowable_error_)
458 << "expected_color: " << std::hex << expected_color
459 << " color: " << color
460 << " Failed at " << std::dec << i << ", " << j
461 << " Failure " << ++fails;
462 EXPECT_NEAR(expected_green, green, allowable_error_)
463 << "expected_color: " << std::hex << expected_color
464 << " color: " << color
465 << " Failed at " << std::dec << i << ", " << j
466 << " Failure " << ++fails;
467 EXPECT_NEAR(expected_blue, blue, allowable_error_)
468 << "expected_color: " << std::hex << expected_color
469 << " color: " << color
470 << " Failed at " << std::dec << i << ", " << j
471 << " Failure " << ++fails;
474 EXPECT_LT(fails, 10);
476 quit_callback.Run();
479 void CopyFromCompositingSurfaceCallbackForVideo(
480 scoped_refptr<media::VideoFrame> video_frame,
481 base::Closure quit_callback,
482 bool result) {
483 EXPECT_EQ(expected_copy_from_compositing_surface_result_, result);
484 if (!result) {
485 quit_callback.Run();
486 return;
489 media::SkCanvasVideoRenderer video_renderer;
491 SkBitmap bitmap;
492 bitmap.allocN32Pixels(video_frame->visible_rect().width(),
493 video_frame->visible_rect().height());
494 // Don't clear the canvas because drawing a video frame by Src mode.
495 SkCanvas canvas(bitmap);
496 video_renderer.Copy(video_frame.get(), &canvas);
498 CopyFromCompositingSurfaceCallback(quit_callback,
499 result,
500 bitmap);
503 void SetExpectedCopyFromCompositingSurfaceResult(bool result,
504 const SkBitmap& bitmap) {
505 expected_copy_from_compositing_surface_result_ = result;
506 expected_copy_from_compositing_surface_bitmap_ = bitmap;
509 void SetAllowableError(int amount) { allowable_error_ = amount; }
510 void SetExcludeRect(gfx::Rect exclude) { exclude_rect_ = exclude; }
512 virtual GURL TestUrl() OVERRIDE {
513 return GURL(test_url_);
516 void SetTestUrl(std::string url) { test_url_ = url; }
518 // Loads a page two boxes side-by-side, each half the width of
519 // |html_rect_size|, and with different background colors. The test then
520 // copies from |copy_rect| region of the page into a bitmap of size
521 // |output_size|, and examines the resulting bitmap/VideoFrame.
522 // Note that |output_size| may not have the same size as |copy_rect| (e.g.
523 // when the output is scaled).
524 void PerformTestWithLeftRightRects(const gfx::Size& html_rect_size,
525 const gfx::Rect& copy_rect,
526 const gfx::Size& output_size,
527 bool video_frame) {
528 const gfx::Size box_size(html_rect_size.width() / 2,
529 html_rect_size.height());
530 SetTestUrl(base::StringPrintf(
531 "data:text/html,<!doctype html>"
532 "<div class='left'>"
533 " <div class='right'></div>"
534 "</div>"
535 "<style>"
536 "body { padding: 0; margin: 0; }"
537 ".left { position: absolute;"
538 " background: #0ff;"
539 " width: %dpx;"
540 " height: %dpx;"
542 ".right { position: absolute;"
543 " left: %dpx;"
544 " background: #ff0;"
545 " width: %dpx;"
546 " height: %dpx;"
548 "</style>"
549 "<script>"
550 " domAutomationController.setAutomationId(0);"
551 " domAutomationController.send(\"DONE\");"
552 "</script>",
553 box_size.width(),
554 box_size.height(),
555 box_size.width(),
556 box_size.width(),
557 box_size.height()));
559 SET_UP_SURFACE_OR_PASS_TEST("\"DONE\"");
560 if (!ShouldContinueAfterTestURLLoad())
561 return;
563 RenderWidgetHostViewBase* rwhvp = GetRenderWidgetHostView();
564 if (video_frame && !rwhvp->CanCopyToVideoFrame()) {
565 // This should only happen on Mac when using the software compositor.
566 // Otherwise, raise an error. This can be removed when Mac is moved to a
567 // browser compositor.
568 // http://crbug.com/314190
569 #if defined(OS_MACOSX)
570 if (!content::GpuDataManager::GetInstance()->GpuAccessAllowed(NULL)) {
571 LOG(WARNING) << ("Blindly passing this test because copying to "
572 "video frames is not supported on this platform.");
573 return;
575 #endif
576 NOTREACHED();
579 // The page is loaded in the renderer, wait for a new frame to arrive.
580 uint32 frame = rwhvp->RendererFrameNumber();
581 while (!GetRenderWidgetHost()->ScheduleComposite())
582 GiveItSomeTime();
583 while (rwhvp->RendererFrameNumber() == frame)
584 GiveItSomeTime();
586 SkBitmap expected_bitmap;
587 SetupLeftRightBitmap(output_size, &expected_bitmap);
588 SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap);
590 base::RunLoop run_loop;
591 if (video_frame) {
592 // Allow pixel differences as long as we have the right idea.
593 SetAllowableError(0x10);
594 // Exclude the middle two columns which are blended between the two sides.
595 SetExcludeRect(
596 gfx::Rect(output_size.width() / 2 - 1, 0, 2, output_size.height()));
598 scoped_refptr<media::VideoFrame> video_frame =
599 media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
600 output_size,
601 gfx::Rect(output_size),
602 output_size,
603 base::TimeDelta());
605 base::Callback<void(bool success)> callback =
606 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
607 CopyFromCompositingSurfaceCallbackForVideo,
608 base::Unretained(this),
609 video_frame,
610 run_loop.QuitClosure());
611 rwhvp->CopyFromCompositingSurfaceToVideoFrame(copy_rect,
612 video_frame,
613 callback);
614 } else {
615 if (IsDelegatedRendererEnabled()) {
616 if (!content::GpuDataManager::GetInstance()
617 ->CanUseGpuBrowserCompositor()) {
618 // Skia rendering can cause color differences, particularly in the
619 // middle two columns.
620 SetAllowableError(2);
621 SetExcludeRect(gfx::Rect(
622 output_size.width() / 2 - 1, 0, 2, output_size.height()));
626 base::Callback<void(bool, const SkBitmap&)> callback =
627 base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
628 CopyFromCompositingSurfaceCallback,
629 base::Unretained(this),
630 run_loop.QuitClosure());
631 rwhvp->CopyFromCompositingSurface(copy_rect,
632 output_size,
633 callback,
634 kN32_SkColorType);
636 run_loop.Run();
639 // Sets up |bitmap| to have size |copy_size|. It floods the left half with
640 // #0ff and the right half with #ff0.
641 void SetupLeftRightBitmap(const gfx::Size& copy_size, SkBitmap* bitmap) {
642 bitmap->allocN32Pixels(copy_size.width(), copy_size.height());
643 // Left half is #0ff.
644 bitmap->eraseARGB(255, 0, 255, 255);
645 // Right half is #ff0.
647 SkAutoLockPixels lock(*bitmap);
648 for (int i = 0; i < copy_size.width() / 2; ++i) {
649 for (int j = 0; j < copy_size.height(); ++j) {
650 *(bitmap->getAddr32(copy_size.width() / 2 + i, j)) =
651 SkColorSetARGB(255, 255, 255, 0);
657 protected:
658 virtual bool ShouldContinueAfterTestURLLoad() {
659 return true;
662 private:
663 bool expected_copy_from_compositing_surface_result_;
664 SkBitmap expected_copy_from_compositing_surface_bitmap_;
665 int allowable_error_;
666 gfx::Rect exclude_rect_;
667 std::string test_url_;
670 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
671 CopyFromCompositingSurface_Origin_Unscaled) {
672 gfx::Rect copy_rect(400, 300);
673 gfx::Size output_size = copy_rect.size();
674 gfx::Size html_rect_size(400, 300);
675 bool video_frame = false;
676 PerformTestWithLeftRightRects(html_rect_size,
677 copy_rect,
678 output_size,
679 video_frame);
682 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
683 CopyFromCompositingSurface_Origin_Scaled) {
684 gfx::Rect copy_rect(400, 300);
685 gfx::Size output_size(200, 100);
686 gfx::Size html_rect_size(400, 300);
687 bool video_frame = false;
688 PerformTestWithLeftRightRects(html_rect_size,
689 copy_rect,
690 output_size,
691 video_frame);
694 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
695 CopyFromCompositingSurface_Cropped_Unscaled) {
696 // Grab 60x60 pixels from the center of the tab contents.
697 gfx::Rect copy_rect(400, 300);
698 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
699 gfx::Size(60, 60));
700 gfx::Size output_size = copy_rect.size();
701 gfx::Size html_rect_size(400, 300);
702 bool video_frame = false;
703 PerformTestWithLeftRightRects(html_rect_size,
704 copy_rect,
705 output_size,
706 video_frame);
709 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
710 CopyFromCompositingSurface_Cropped_Scaled) {
711 // Grab 60x60 pixels from the center of the tab contents.
712 gfx::Rect copy_rect(400, 300);
713 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
714 gfx::Size(60, 60));
715 gfx::Size output_size(20, 10);
716 gfx::Size html_rect_size(400, 300);
717 bool video_frame = false;
718 PerformTestWithLeftRightRects(html_rect_size,
719 copy_rect,
720 output_size,
721 video_frame);
724 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
725 CopyFromCompositingSurface_ForVideoFrame) {
726 // Grab 90x60 pixels from the center of the tab contents.
727 gfx::Rect copy_rect(400, 300);
728 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(45, 30),
729 gfx::Size(90, 60));
730 gfx::Size output_size = copy_rect.size();
731 gfx::Size html_rect_size(400, 300);
732 bool video_frame = true;
733 PerformTestWithLeftRightRects(html_rect_size,
734 copy_rect,
735 output_size,
736 video_frame);
739 IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
740 CopyFromCompositingSurface_ForVideoFrame_Scaled) {
741 // Grab 90x60 pixels from the center of the tab contents.
742 gfx::Rect copy_rect(400, 300);
743 copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(45, 30),
744 gfx::Size(90, 60));
745 // Scale to 30 x 20 (preserve aspect ratio).
746 gfx::Size output_size(30, 20);
747 gfx::Size html_rect_size(400, 300);
748 bool video_frame = true;
749 PerformTestWithLeftRightRects(html_rect_size,
750 copy_rect,
751 output_size,
752 video_frame);
755 class CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
756 : public CompositingRenderWidgetHostViewBrowserTestTabCapture {
757 public:
758 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI() {}
760 protected:
761 virtual void SetUpCommandLine(base::CommandLine* cmd) OVERRIDE {
762 CompositingRenderWidgetHostViewBrowserTestTabCapture::SetUpCommandLine(cmd);
763 cmd->AppendSwitchASCII(switches::kForceDeviceScaleFactor,
764 base::StringPrintf("%f", scale()));
767 virtual bool ShouldContinueAfterTestURLLoad() OVERRIDE {
768 // Short-circuit a pass for platforms where setting up high-DPI fails.
769 const float actual_scale_factor =
770 GetScaleFactorForView(GetRenderWidgetHostView());
771 if (actual_scale_factor != scale()) {
772 LOG(WARNING) << "Blindly passing this test; unable to force device scale "
773 << "factor: seems to be " << actual_scale_factor
774 << " but expected " << scale();
775 return false;
777 VLOG(1) << ("Successfully forced device scale factor. Moving forward with "
778 "this test! :-)");
779 return true;
782 static float scale() { return 2.0f; }
784 private:
785 DISALLOW_COPY_AND_ASSIGN(
786 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI);
789 // ImageSkia (related to ResourceBundle) implementation crashes the process on
790 // Windows when this content_browsertest forces a device scale factor.
791 // http://crbug.com/399349
793 // These tests are flaky on ChromeOS builders. See http://crbug.com/406018.
794 #if defined(OS_WIN) || defined(OS_CHROMEOS)
795 #define MAYBE_CopyToBitmap_EntireRegion DISABLED_CopyToBitmap_EntireRegion
796 #define MAYBE_CopyToBitmap_CenterRegion DISABLED_CopyToBitmap_CenterRegion
797 #define MAYBE_CopyToBitmap_ScaledResult DISABLED_CopyToBitmap_ScaledResult
798 #define MAYBE_CopyToVideoFrame_EntireRegion \
799 DISABLED_CopyToVideoFrame_EntireRegion
800 #define MAYBE_CopyToVideoFrame_CenterRegion \
801 DISABLED_CopyToVideoFrame_CenterRegion
802 #define MAYBE_CopyToVideoFrame_ScaledResult \
803 DISABLED_CopyToVideoFrame_ScaledResult
804 #else
805 #define MAYBE_CopyToBitmap_EntireRegion CopyToBitmap_EntireRegion
806 #define MAYBE_CopyToBitmap_CenterRegion CopyToBitmap_CenterRegion
807 #define MAYBE_CopyToBitmap_ScaledResult CopyToBitmap_ScaledResult
808 #define MAYBE_CopyToVideoFrame_EntireRegion CopyToVideoFrame_EntireRegion
809 #define MAYBE_CopyToVideoFrame_CenterRegion CopyToVideoFrame_CenterRegion
810 #define MAYBE_CopyToVideoFrame_ScaledResult CopyToVideoFrame_ScaledResult
811 #endif
813 IN_PROC_BROWSER_TEST_P(
814 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
815 MAYBE_CopyToBitmap_EntireRegion) {
816 gfx::Size html_rect_size(200, 150);
817 gfx::Rect copy_rect(200, 150);
818 // Scale the output size so that, internally, scaling is not occurring.
819 gfx::Size output_size =
820 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
821 bool video_frame = false;
822 PerformTestWithLeftRightRects(html_rect_size,
823 copy_rect,
824 output_size,
825 video_frame);
828 IN_PROC_BROWSER_TEST_P(
829 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
830 MAYBE_CopyToBitmap_CenterRegion) {
831 gfx::Size html_rect_size(200, 150);
832 // Grab 90x60 pixels from the center of the tab contents.
833 gfx::Rect copy_rect =
834 gfx::Rect(gfx::Rect(html_rect_size).CenterPoint() - gfx::Vector2d(45, 30),
835 gfx::Size(90, 60));
836 // Scale the output size so that, internally, scaling is not occurring.
837 gfx::Size output_size =
838 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
839 bool video_frame = false;
840 PerformTestWithLeftRightRects(html_rect_size,
841 copy_rect,
842 output_size,
843 video_frame);
846 IN_PROC_BROWSER_TEST_P(
847 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
848 MAYBE_CopyToBitmap_ScaledResult) {
849 gfx::Size html_rect_size(200, 100);
850 gfx::Rect copy_rect(200, 100);
851 // Output is being down-scaled since output_size is in phyiscal pixels.
852 gfx::Size output_size(200, 100);
853 bool video_frame = false;
854 PerformTestWithLeftRightRects(html_rect_size,
855 copy_rect,
856 output_size,
857 video_frame);
860 IN_PROC_BROWSER_TEST_P(
861 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
862 MAYBE_CopyToVideoFrame_EntireRegion) {
863 gfx::Size html_rect_size(200, 150);
864 gfx::Rect copy_rect(200, 150);
865 // Scale the output size so that, internally, scaling is not occurring.
866 gfx::Size output_size =
867 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
868 bool video_frame = true;
869 PerformTestWithLeftRightRects(html_rect_size,
870 copy_rect,
871 output_size,
872 video_frame);
875 IN_PROC_BROWSER_TEST_P(
876 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
877 MAYBE_CopyToVideoFrame_CenterRegion) {
878 gfx::Size html_rect_size(200, 150);
879 // Grab 90x60 pixels from the center of the tab contents.
880 gfx::Rect copy_rect =
881 gfx::Rect(gfx::Rect(html_rect_size).CenterPoint() - gfx::Vector2d(45, 30),
882 gfx::Size(90, 60));
883 // Scale the output size so that, internally, scaling is not occurring.
884 gfx::Size output_size =
885 gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
886 bool video_frame = true;
887 PerformTestWithLeftRightRects(html_rect_size,
888 copy_rect,
889 output_size,
890 video_frame);
893 IN_PROC_BROWSER_TEST_P(
894 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
895 MAYBE_CopyToVideoFrame_ScaledResult) {
896 gfx::Size html_rect_size(200, 100);
897 gfx::Rect copy_rect(200, 100);
898 // Output is being down-scaled since output_size is in phyiscal pixels.
899 gfx::Size output_size(200, 100);
900 bool video_frame = true;
901 PerformTestWithLeftRightRects(html_rect_size,
902 copy_rect,
903 output_size,
904 video_frame);
907 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
908 CompositingRenderWidgetHostViewBrowserTest,
909 testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
910 INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
911 CompositingRenderWidgetHostViewBrowserTestTabCapture,
912 testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
913 INSTANTIATE_TEST_CASE_P(
914 GLAndSoftwareCompositing,
915 CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
916 testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
918 #endif // !defined(OS_ANDROID) && !defined(OS_IOS)
920 } // namespace
921 } // namespace content