Move VISUAL_STATE promise to activation
[chromium-blink-merge.git] / content / renderer / gpu / render_widget_compositor_unittest.cc
blobe42fb5845b716cfc8476405baf1ba7aa79552417
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 "cc/output/begin_frame_args.h"
8 #include "cc/test/failure_output_surface.h"
9 #include "cc/trees/layer_tree_host.h"
10 #include "components/scheduler/renderer/renderer_scheduler.h"
11 #include "content/public/test/mock_render_thread.h"
12 #include "content/renderer/render_widget.h"
13 #include "content/test/fake_compositor_dependencies.h"
14 #include "content/test/fake_renderer_scheduler.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
19 using testing::AllOf;
20 using testing::Field;
22 namespace content {
23 namespace {
25 class MockWebWidget : public blink::WebWidget {
26 public:
27 MOCK_METHOD1(beginFrame, void(const blink::WebBeginFrameArgs& args));
30 class TestRenderWidget : public RenderWidget {
31 public:
32 TestRenderWidget()
33 : RenderWidget(blink::WebPopupTypeNone,
34 blink::WebScreenInfo(),
35 true,
36 false,
37 false) {
38 webwidget_ = &mock_webwidget_;
41 MockWebWidget mock_webwidget_;
43 protected:
44 ~TestRenderWidget() override { webwidget_ = NULL; }
46 DISALLOW_COPY_AND_ASSIGN(TestRenderWidget);
49 class RenderWidgetCompositorTest : public testing::Test {
50 public:
51 RenderWidgetCompositorTest()
52 : render_widget_(make_scoped_refptr(new TestRenderWidget())),
53 compositor_deps_(make_scoped_ptr(new FakeCompositorDependencies)),
54 render_widget_compositor_(
55 RenderWidgetCompositor::Create(render_widget_.get(),
56 compositor_deps_.get())) {}
57 ~RenderWidgetCompositorTest() override {}
59 protected:
60 base::MessageLoop loop_;
61 MockRenderThread render_thread_;
62 scoped_refptr<TestRenderWidget> render_widget_;
63 scoped_ptr<FakeCompositorDependencies> compositor_deps_;
64 scoped_ptr<RenderWidgetCompositor> render_widget_compositor_;
66 private:
67 DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositorTest);
70 TEST_F(RenderWidgetCompositorTest, BeginMainFrame) {
71 base::TimeTicks frame_time(base::TimeTicks() +
72 base::TimeDelta::FromSeconds(1));
73 base::TimeTicks deadline(base::TimeTicks() + base::TimeDelta::FromSeconds(2));
74 base::TimeDelta interval(base::TimeDelta::FromSeconds(3));
75 cc::BeginFrameArgs args(
76 cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
77 interval, cc::BeginFrameArgs::NORMAL));
79 EXPECT_CALL(render_widget_->mock_webwidget_,
80 beginFrame(AllOf(
81 Field(&blink::WebBeginFrameArgs::lastFrameTimeMonotonic, 1),
82 Field(&blink::WebBeginFrameArgs::deadline, 2),
83 Field(&blink::WebBeginFrameArgs::interval, 3))));
85 render_widget_compositor_->BeginMainFrame(args);
88 class RenderWidgetCompositorOutputSurface;
90 class RenderWidgetOutputSurface : public TestRenderWidget {
91 public:
92 RenderWidgetOutputSurface() : compositor_(NULL) {}
93 void SetCompositor(RenderWidgetCompositorOutputSurface* compositor);
95 scoped_ptr<cc::OutputSurface> CreateOutputSurface(bool fallback) override;
97 protected:
98 ~RenderWidgetOutputSurface() override {}
100 private:
101 RenderWidgetCompositorOutputSurface* compositor_;
103 DISALLOW_COPY_AND_ASSIGN(RenderWidgetOutputSurface);
106 // Verify that failing to create an output surface will cause the compositor
107 // to attempt to repeatedly create another output surface. After enough
108 // failures, verify that it attempts to create a fallback output surface.
109 // The use null output surface parameter allows testing whether failures
110 // from RenderWidget (couldn't create an output surface) vs failures from
111 // the compositor (couldn't bind the output surface) are handled identically.
112 class RenderWidgetCompositorOutputSurface : public RenderWidgetCompositor {
113 public:
114 RenderWidgetCompositorOutputSurface(RenderWidget* widget,
115 CompositorDependencies* compositor_deps)
116 : RenderWidgetCompositor(widget, compositor_deps),
117 num_failures_before_success_(0),
118 expected_successes_(0),
119 expected_fallback_successes_(0),
120 expected_requests_(0),
121 num_requests_(0),
122 num_requests_since_last_success_(0),
123 num_successes_(0),
124 num_fallback_successes_(0),
125 num_failures_(0),
126 last_create_was_fallback_(false),
127 use_null_output_surface_(true) {}
129 using RenderWidgetCompositor::Initialize;
131 scoped_ptr<cc::OutputSurface> CreateOutputSurface(bool fallback) {
132 EXPECT_EQ(num_requests_since_last_success_ >
133 OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK,
134 fallback);
135 last_create_was_fallback_ = fallback;
136 bool success = num_failures_ >= num_failures_before_success_;
137 if (success) {
138 scoped_ptr<cc::TestWebGraphicsContext3D> context =
139 cc::TestWebGraphicsContext3D::Create();
140 // Image support required for synchronous compositing.
141 context->set_support_image(true);
142 return cc::FakeOutputSurface::Create3d(context.Pass());
144 return use_null_output_surface_
145 ? nullptr
146 : make_scoped_ptr(new cc::FailureOutputSurface(false));
149 // Force a new output surface to be created.
150 void SynchronousComposite() {
151 layer_tree_host()->DidLoseOutputSurface();
153 base::TimeTicks some_time;
154 layer_tree_host()->Composite(some_time);
157 void RequestNewOutputSurface() override {
158 ++num_requests_;
159 ++num_requests_since_last_success_;
160 RenderWidgetCompositor::RequestNewOutputSurface();
163 void DidInitializeOutputSurface() override {
164 if (last_create_was_fallback_)
165 ++num_fallback_successes_;
166 else
167 ++num_successes_;
169 if (num_requests_ == expected_requests_) {
170 EndTest();
171 } else {
172 num_requests_since_last_success_ = 0;
173 RenderWidgetCompositor::DidInitializeOutputSurface();
174 // Post the synchronous composite task so that it is not called
175 // reentrantly as a part of RequestNewOutputSurface.
176 base::MessageLoop::current()->PostTask(
177 FROM_HERE,
178 base::Bind(&RenderWidgetCompositorOutputSurface::SynchronousComposite,
179 base::Unretained(this)));
183 void DidFailToInitializeOutputSurface() override {
184 ++num_failures_;
185 if (num_requests_ == expected_requests_) {
186 EndTest();
187 return;
190 RenderWidgetCompositor::DidFailToInitializeOutputSurface();
193 void SetUp(bool use_null_output_surface,
194 int num_failures_before_success,
195 int expected_successes,
196 int expected_fallback_succeses) {
197 use_null_output_surface_ = use_null_output_surface;
198 num_failures_before_success_ = num_failures_before_success;
199 expected_successes_ = expected_successes;
200 expected_fallback_successes_ = expected_fallback_succeses;
201 expected_requests_ = num_failures_before_success_ + expected_successes_ +
202 expected_fallback_successes_;
205 void EndTest() { base::MessageLoop::current()->Quit(); }
207 void AfterTest() {
208 EXPECT_EQ(num_failures_before_success_, num_failures_);
209 EXPECT_EQ(expected_successes_, num_successes_);
210 EXPECT_EQ(expected_fallback_successes_, num_fallback_successes_);
211 EXPECT_EQ(expected_requests_, num_requests_);
214 private:
215 int num_failures_before_success_;
216 int expected_successes_;
217 int expected_fallback_successes_;
218 int expected_requests_;
219 int num_requests_;
220 int num_requests_since_last_success_;
221 int num_successes_;
222 int num_fallback_successes_;
223 int num_failures_;
224 bool last_create_was_fallback_;
225 bool use_null_output_surface_;
227 DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositorOutputSurface);
230 class RenderWidgetCompositorOutputSurfaceTest : public testing::Test {
231 public:
232 RenderWidgetCompositorOutputSurfaceTest()
233 : render_widget_(make_scoped_refptr(new RenderWidgetOutputSurface)),
234 compositor_deps_(make_scoped_ptr(new FakeCompositorDependencies)) {
235 // Required in order to call the synchronous LayerTreeHost::Composite.
236 compositor_deps_->set_use_single_thread_scheduler(false);
237 render_widget_compositor_.reset(new RenderWidgetCompositorOutputSurface(
238 render_widget_.get(), compositor_deps_.get()));
239 render_widget_compositor_->Initialize();
240 render_widget_->SetCompositor(render_widget_compositor_.get());
243 void RunTest(bool use_null_output_surface,
244 int num_failures_before_success,
245 int expected_successes,
246 int expected_fallback_succeses) {
247 render_widget_compositor_->SetUp(
248 use_null_output_surface, num_failures_before_success,
249 expected_successes, expected_fallback_succeses);
250 render_widget_compositor_->StartCompositor();
251 base::MessageLoop::current()->PostTask(
252 FROM_HERE,
253 base::Bind(&RenderWidgetCompositorOutputSurface::SynchronousComposite,
254 base::Unretained(render_widget_compositor_.get())));
255 base::MessageLoop::current()->Run();
256 render_widget_compositor_->AfterTest();
259 protected:
260 base::MessageLoop ye_olde_message_loope_;
261 MockRenderThread render_thread_;
262 scoped_refptr<RenderWidgetOutputSurface> render_widget_;
263 scoped_ptr<FakeCompositorDependencies> compositor_deps_;
264 scoped_ptr<RenderWidgetCompositorOutputSurface> render_widget_compositor_;
266 private:
267 DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositorOutputSurfaceTest);
270 scoped_ptr<cc::OutputSurface> RenderWidgetOutputSurface::CreateOutputSurface(
271 bool fallback) {
272 return compositor_->CreateOutputSurface(fallback);
275 void RenderWidgetOutputSurface::SetCompositor(
276 RenderWidgetCompositorOutputSurface* compositor) {
277 compositor_ = compositor;
280 TEST_F(RenderWidgetCompositorOutputSurfaceTest, SucceedOnce) {
281 RunTest(false, 0, 1, 0);
284 TEST_F(RenderWidgetCompositorOutputSurfaceTest, SucceedTwice) {
285 RunTest(false, 0, 2, 0);
288 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FailOnceNull) {
289 static_assert(
290 RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK >= 2,
291 "Adjust the values of this test if this fails");
292 RunTest(true, 1, 1, 0);
295 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FailOnceBind) {
296 static_assert(
297 RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK >= 2,
298 "Adjust the values of this test if this fails");
299 RunTest(false, 1, 1, 0);
302 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FallbackSuccessNull) {
303 RunTest(true, RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK,
304 0, 1);
307 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FallbackSuccessBind) {
308 RunTest(false, RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK,
309 0, 1);
312 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FallbackSuccessNormalSuccess) {
313 // The first success is a fallback, but the next should not be a fallback.
314 RunTest(false, RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK,
315 1, 1);
318 } // namespace
319 } // namespace content