Roll src/third_party/skia 726cf90:183b57f
[chromium-blink-merge.git] / content / renderer / gpu / render_widget_compositor_unittest.cc
blob35774b77d813e1d2ec84b517c49b6110ecdaa7e5
1 // Copyright 2014 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 "content/renderer/gpu/render_widget_compositor.h"
7 #include "base/location.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "cc/output/begin_frame_args.h"
11 #include "cc/test/failure_output_surface.h"
12 #include "cc/trees/layer_tree_host.h"
13 #include "components/scheduler/renderer/renderer_scheduler.h"
14 #include "content/public/test/mock_render_thread.h"
15 #include "content/renderer/render_widget.h"
16 #include "content/test/fake_compositor_dependencies.h"
17 #include "content/test/fake_renderer_scheduler.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
22 using testing::AllOf;
23 using testing::Field;
25 namespace content {
26 namespace {
28 class MockWebWidget : public blink::WebWidget {
29 public:
30 MOCK_METHOD1(beginFrame, void(const blink::WebBeginFrameArgs& args));
33 class TestRenderWidget : public RenderWidget {
34 public:
35 TestRenderWidget()
36 : RenderWidget(blink::WebPopupTypeNone,
37 blink::WebScreenInfo(),
38 true,
39 false,
40 false) {
41 webwidget_ = &mock_webwidget_;
44 MockWebWidget mock_webwidget_;
46 protected:
47 ~TestRenderWidget() override { webwidget_ = NULL; }
49 DISALLOW_COPY_AND_ASSIGN(TestRenderWidget);
52 class RenderWidgetCompositorTest : public testing::Test {
53 public:
54 RenderWidgetCompositorTest()
55 : render_widget_(make_scoped_refptr(new TestRenderWidget())),
56 compositor_deps_(make_scoped_ptr(new FakeCompositorDependencies)),
57 render_widget_compositor_(
58 RenderWidgetCompositor::Create(render_widget_.get(),
59 compositor_deps_.get())) {}
60 ~RenderWidgetCompositorTest() override {}
62 protected:
63 base::MessageLoop loop_;
64 MockRenderThread render_thread_;
65 scoped_refptr<TestRenderWidget> render_widget_;
66 scoped_ptr<FakeCompositorDependencies> compositor_deps_;
67 scoped_ptr<RenderWidgetCompositor> render_widget_compositor_;
69 private:
70 DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositorTest);
73 TEST_F(RenderWidgetCompositorTest, BeginMainFrame) {
74 base::TimeTicks frame_time(base::TimeTicks() +
75 base::TimeDelta::FromSeconds(1));
76 base::TimeTicks deadline(base::TimeTicks() + base::TimeDelta::FromSeconds(2));
77 base::TimeDelta interval(base::TimeDelta::FromSeconds(3));
78 cc::BeginFrameArgs args(
79 cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
80 interval, cc::BeginFrameArgs::NORMAL));
82 EXPECT_CALL(render_widget_->mock_webwidget_,
83 beginFrame(AllOf(
84 Field(&blink::WebBeginFrameArgs::lastFrameTimeMonotonic, 1),
85 Field(&blink::WebBeginFrameArgs::deadline, 2),
86 Field(&blink::WebBeginFrameArgs::interval, 3))));
88 render_widget_compositor_->BeginMainFrame(args);
91 class RenderWidgetCompositorOutputSurface;
93 class RenderWidgetOutputSurface : public TestRenderWidget {
94 public:
95 RenderWidgetOutputSurface() : compositor_(NULL) {}
96 void SetCompositor(RenderWidgetCompositorOutputSurface* compositor);
98 scoped_ptr<cc::OutputSurface> CreateOutputSurface(bool fallback) override;
100 protected:
101 ~RenderWidgetOutputSurface() override {}
103 private:
104 RenderWidgetCompositorOutputSurface* compositor_;
106 DISALLOW_COPY_AND_ASSIGN(RenderWidgetOutputSurface);
109 // Verify that failing to create an output surface will cause the compositor
110 // to attempt to repeatedly create another output surface. After enough
111 // failures, verify that it attempts to create a fallback output surface.
112 // The use null output surface parameter allows testing whether failures
113 // from RenderWidget (couldn't create an output surface) vs failures from
114 // the compositor (couldn't bind the output surface) are handled identically.
115 class RenderWidgetCompositorOutputSurface : public RenderWidgetCompositor {
116 public:
117 RenderWidgetCompositorOutputSurface(RenderWidget* widget,
118 CompositorDependencies* compositor_deps)
119 : RenderWidgetCompositor(widget, compositor_deps),
120 num_failures_before_success_(0),
121 expected_successes_(0),
122 expected_fallback_successes_(0),
123 expected_requests_(0),
124 num_requests_(0),
125 num_requests_since_last_success_(0),
126 num_successes_(0),
127 num_fallback_successes_(0),
128 num_failures_(0),
129 last_create_was_fallback_(false),
130 use_null_output_surface_(true) {}
132 using RenderWidgetCompositor::Initialize;
134 scoped_ptr<cc::OutputSurface> CreateOutputSurface(bool fallback) {
135 EXPECT_EQ(num_requests_since_last_success_ >
136 OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK,
137 fallback);
138 last_create_was_fallback_ = fallback;
139 bool success = num_failures_ >= num_failures_before_success_;
140 if (success) {
141 scoped_ptr<cc::TestWebGraphicsContext3D> context =
142 cc::TestWebGraphicsContext3D::Create();
143 // Image support required for synchronous compositing.
144 context->set_support_image(true);
145 return cc::FakeOutputSurface::Create3d(context.Pass());
147 return use_null_output_surface_
148 ? nullptr
149 : make_scoped_ptr(new cc::FailureOutputSurface(false));
152 // Force a new output surface to be created.
153 void SynchronousComposite() {
154 layer_tree_host()->DidLoseOutputSurface();
156 base::TimeTicks some_time;
157 layer_tree_host()->Composite(some_time);
160 void RequestNewOutputSurface() override {
161 ++num_requests_;
162 ++num_requests_since_last_success_;
163 RenderWidgetCompositor::RequestNewOutputSurface();
166 void DidInitializeOutputSurface() override {
167 if (last_create_was_fallback_)
168 ++num_fallback_successes_;
169 else
170 ++num_successes_;
172 if (num_requests_ == expected_requests_) {
173 EndTest();
174 } else {
175 num_requests_since_last_success_ = 0;
176 RenderWidgetCompositor::DidInitializeOutputSurface();
177 // Post the synchronous composite task so that it is not called
178 // reentrantly as a part of RequestNewOutputSurface.
179 base::ThreadTaskRunnerHandle::Get()->PostTask(
180 FROM_HERE,
181 base::Bind(&RenderWidgetCompositorOutputSurface::SynchronousComposite,
182 base::Unretained(this)));
186 void DidFailToInitializeOutputSurface() override {
187 ++num_failures_;
188 if (num_requests_ == expected_requests_) {
189 EndTest();
190 return;
193 RenderWidgetCompositor::DidFailToInitializeOutputSurface();
196 void SetUp(bool use_null_output_surface,
197 int num_failures_before_success,
198 int expected_successes,
199 int expected_fallback_succeses) {
200 use_null_output_surface_ = use_null_output_surface;
201 num_failures_before_success_ = num_failures_before_success;
202 expected_successes_ = expected_successes;
203 expected_fallback_successes_ = expected_fallback_succeses;
204 expected_requests_ = num_failures_before_success_ + expected_successes_ +
205 expected_fallback_successes_;
208 void EndTest() { base::MessageLoop::current()->Quit(); }
210 void AfterTest() {
211 EXPECT_EQ(num_failures_before_success_, num_failures_);
212 EXPECT_EQ(expected_successes_, num_successes_);
213 EXPECT_EQ(expected_fallback_successes_, num_fallback_successes_);
214 EXPECT_EQ(expected_requests_, num_requests_);
217 private:
218 int num_failures_before_success_;
219 int expected_successes_;
220 int expected_fallback_successes_;
221 int expected_requests_;
222 int num_requests_;
223 int num_requests_since_last_success_;
224 int num_successes_;
225 int num_fallback_successes_;
226 int num_failures_;
227 bool last_create_was_fallback_;
228 bool use_null_output_surface_;
230 DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositorOutputSurface);
233 class RenderWidgetCompositorOutputSurfaceTest : public testing::Test {
234 public:
235 RenderWidgetCompositorOutputSurfaceTest()
236 : render_widget_(make_scoped_refptr(new RenderWidgetOutputSurface)),
237 compositor_deps_(make_scoped_ptr(new FakeCompositorDependencies)) {
238 render_widget_compositor_.reset(new RenderWidgetCompositorOutputSurface(
239 render_widget_.get(), compositor_deps_.get()));
240 render_widget_compositor_->Initialize();
241 render_widget_->SetCompositor(render_widget_compositor_.get());
244 void RunTest(bool use_null_output_surface,
245 int num_failures_before_success,
246 int expected_successes,
247 int expected_fallback_succeses) {
248 render_widget_compositor_->SetUp(
249 use_null_output_surface, num_failures_before_success,
250 expected_successes, expected_fallback_succeses);
251 render_widget_compositor_->StartCompositor();
252 base::ThreadTaskRunnerHandle::Get()->PostTask(
253 FROM_HERE,
254 base::Bind(&RenderWidgetCompositorOutputSurface::SynchronousComposite,
255 base::Unretained(render_widget_compositor_.get())));
256 base::MessageLoop::current()->Run();
257 render_widget_compositor_->AfterTest();
260 protected:
261 base::MessageLoop ye_olde_message_loope_;
262 MockRenderThread render_thread_;
263 scoped_refptr<RenderWidgetOutputSurface> render_widget_;
264 scoped_ptr<FakeCompositorDependencies> compositor_deps_;
265 scoped_ptr<RenderWidgetCompositorOutputSurface> render_widget_compositor_;
267 private:
268 DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositorOutputSurfaceTest);
271 scoped_ptr<cc::OutputSurface> RenderWidgetOutputSurface::CreateOutputSurface(
272 bool fallback) {
273 return compositor_->CreateOutputSurface(fallback);
276 void RenderWidgetOutputSurface::SetCompositor(
277 RenderWidgetCompositorOutputSurface* compositor) {
278 compositor_ = compositor;
281 TEST_F(RenderWidgetCompositorOutputSurfaceTest, SucceedOnce) {
282 RunTest(false, 0, 1, 0);
285 TEST_F(RenderWidgetCompositorOutputSurfaceTest, SucceedTwice) {
286 RunTest(false, 0, 2, 0);
289 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FailOnceNull) {
290 static_assert(
291 RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK >= 2,
292 "Adjust the values of this test if this fails");
293 RunTest(true, 1, 1, 0);
296 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FailOnceBind) {
297 static_assert(
298 RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK >= 2,
299 "Adjust the values of this test if this fails");
300 RunTest(false, 1, 1, 0);
303 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FallbackSuccessNull) {
304 RunTest(true, RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK,
305 0, 1);
308 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FallbackSuccessBind) {
309 RunTest(false, RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK,
310 0, 1);
313 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FallbackSuccessNormalSuccess) {
314 // The first success is a fallback, but the next should not be a fallback.
315 RunTest(false, RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK,
316 1, 1);
319 } // namespace
320 } // namespace content