Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/gpu/render_widget_compositor.h" | 5 #include "content/renderer/gpu/render_widget_compositor.h" |
| 6 | 6 |
| 7 #include "cc/output/begin_frame_args.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" | |
| 8 #include "content/public/test/mock_render_thread.h" | 10 #include "content/public/test/mock_render_thread.h" |
| 9 #include "content/renderer/render_widget.h" | 11 #include "content/renderer/render_widget.h" |
| 10 #include "testing/gmock/include/gmock/gmock.h" | 12 #include "testing/gmock/include/gmock/gmock.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
| 12 #include "third_party/WebKit/public/platform/WebScreenInfo.h" | 14 #include "third_party/WebKit/public/platform/WebScreenInfo.h" |
| 13 | 15 |
| 14 using testing::AllOf; | 16 using testing::AllOf; |
| 15 using testing::Field; | 17 using testing::Field; |
| 16 | 18 |
| 17 namespace content { | 19 namespace content { |
| 18 | 20 |
| 19 class MockWebWidget : public blink::WebWidget { | 21 class MockWebWidget : public blink::WebWidget { |
| 20 public: | 22 public: |
| 21 MOCK_METHOD1(beginFrame, void(const blink::WebBeginFrameArgs& args)); | 23 MOCK_METHOD1(beginFrame, void(const blink::WebBeginFrameArgs& args)); |
| 22 }; | 24 }; |
| 23 | 25 |
| 24 class TestRenderWidget : public RenderWidget { | 26 class TestRenderWidget : public RenderWidget { |
| 25 public: | 27 public: |
| 26 TestRenderWidget() | 28 TestRenderWidget() |
| 27 : RenderWidget(blink::WebPopupTypeNone, | 29 : RenderWidget(blink::WebPopupTypeNone, |
| 28 blink::WebScreenInfo(), | 30 blink::WebScreenInfo(), |
| 29 true, | 31 true, |
| 30 false, | 32 false, |
| 31 false) { | 33 false) { |
| 32 webwidget_ = &mock_webwidget_; | 34 webwidget_ = &mock_webwidget_; |
| 33 } | 35 } |
| 34 | 36 |
| 35 MockWebWidget mock_webwidget_; | 37 MockWebWidget mock_webwidget_; |
| 36 | 38 |
| 37 private: | 39 protected: |
| 38 ~TestRenderWidget() override { webwidget_ = NULL; } | 40 ~TestRenderWidget() override { webwidget_ = NULL; } |
| 39 | 41 |
| 40 DISALLOW_COPY_AND_ASSIGN(TestRenderWidget); | 42 DISALLOW_COPY_AND_ASSIGN(TestRenderWidget); |
| 41 }; | 43 }; |
| 42 | 44 |
| 43 class RenderWidgetCompositorTest : public testing::Test { | 45 class RenderWidgetCompositorTest : public testing::Test { |
| 44 public: | 46 public: |
| 45 RenderWidgetCompositorTest() | 47 RenderWidgetCompositorTest() |
| 46 : render_widget_(make_scoped_refptr(new TestRenderWidget())), | 48 : render_widget_(make_scoped_refptr(new TestRenderWidget())), |
| 47 render_widget_compositor_( | 49 render_widget_compositor_( |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 68 | 70 |
| 69 EXPECT_CALL(render_widget_->mock_webwidget_, | 71 EXPECT_CALL(render_widget_->mock_webwidget_, |
| 70 beginFrame(AllOf( | 72 beginFrame(AllOf( |
| 71 Field(&blink::WebBeginFrameArgs::lastFrameTimeMonotonic, 1), | 73 Field(&blink::WebBeginFrameArgs::lastFrameTimeMonotonic, 1), |
| 72 Field(&blink::WebBeginFrameArgs::deadline, 2), | 74 Field(&blink::WebBeginFrameArgs::deadline, 2), |
| 73 Field(&blink::WebBeginFrameArgs::interval, 3)))); | 75 Field(&blink::WebBeginFrameArgs::interval, 3)))); |
| 74 | 76 |
| 75 render_widget_compositor_->BeginMainFrame(args); | 77 render_widget_compositor_->BeginMainFrame(args); |
| 76 } | 78 } |
| 77 | 79 |
| 80 class RenderWidgetCompositorOutputSurface; | |
| 81 | |
| 82 class RenderWidgetOutputSurface : public TestRenderWidget { | |
| 83 public: | |
| 84 RenderWidgetOutputSurface() : compositor_(NULL) {} | |
| 85 void SetCompositor(RenderWidgetCompositorOutputSurface* compositor); | |
| 86 | |
| 87 scoped_ptr<cc::OutputSurface> CreateOutputSurface(bool fallback) override; | |
| 88 | |
| 89 protected: | |
| 90 ~RenderWidgetOutputSurface() {} | |
| 91 | |
| 92 private: | |
| 93 RenderWidgetCompositorOutputSurface* compositor_; | |
| 94 | |
| 95 DISALLOW_COPY_AND_ASSIGN(RenderWidgetOutputSurface); | |
| 96 }; | |
| 97 | |
| 98 // Verify that failing to create an output surface will cause the compositor | |
| 99 // to attempt to repeatedly create another output surface. After enough | |
| 100 // failures, verify that it attempts to create a fallback output surface. | |
| 101 // The use null output surface parameter allows testing whether failures | |
| 102 // from RenderWidget (couldn't create an output surface) vs failures from | |
| 103 // the compositor (couldn't bind the output surface) are handled identically. | |
| 104 class RenderWidgetCompositorOutputSurface : public RenderWidgetCompositor { | |
| 105 public: | |
| 106 RenderWidgetCompositorOutputSurface(RenderWidget* widget, bool threaded) | |
| 107 : RenderWidgetCompositor(widget, threaded), | |
| 108 expected_failures_(0), | |
| 109 expected_successes_(0), | |
| 110 expected_fallback_successes_(0), | |
| 111 expected_requests_(0), | |
| 112 num_requests_(0), | |
| 113 num_requests_since_last_success_(0), | |
| 114 num_successes_(0), | |
| 115 num_fallback_successes_(0), | |
| 116 num_failures_(0), | |
| 117 last_create_was_fallback_(false), | |
| 118 use_null_output_surface_(true) { | |
| 119 cc::LayerTreeSettings settings; | |
| 120 Initialize(settings); | |
| 121 } | |
| 122 | |
| 123 scoped_ptr<cc::OutputSurface> CreateOutputSurface(bool fallback) { | |
| 124 EXPECT_EQ(num_requests_since_last_success_ > | |
| 125 OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK, | |
| 126 fallback); | |
| 127 last_create_was_fallback_ = fallback; | |
| 128 bool success = num_failures_ >= expected_failures_; | |
| 129 if (success) | |
| 130 return cc::FakeOutputSurface::Create3d(); | |
| 131 return use_null_output_surface_ | |
| 132 ? nullptr | |
| 133 : make_scoped_ptr(new cc::FailureOutputSurface(false)); | |
| 134 } | |
| 135 | |
| 136 void RequestNewOutputSurface() override { | |
| 137 ++num_requests_; | |
| 138 ++num_requests_since_last_success_; | |
| 139 RenderWidgetCompositor::RequestNewOutputSurface(); | |
| 140 } | |
| 141 | |
| 142 void DidInitializeOutputSurface() override { | |
| 143 if (last_create_was_fallback_) | |
| 144 ++num_fallback_successes_; | |
| 145 else | |
| 146 ++num_successes_; | |
| 147 | |
| 148 if (num_requests_ == expected_requests_) { | |
| 149 EndTest(); | |
| 150 } else { | |
| 151 num_requests_since_last_success_ = 0; | |
| 152 RenderWidgetCompositor::DidInitializeOutputSurface(); | |
| 153 layer_tree_host()->DidLoseOutputSurface(); | |
| 154 RequestNewOutputSurface(); | |
| 155 } | |
| 156 } | |
| 157 | |
| 158 void DidFailToInitializeOutputSurface() override { | |
| 159 ++num_failures_; | |
| 160 if (num_requests_ == expected_requests_) { | |
| 161 EndTest(); | |
| 162 return; | |
| 163 } | |
| 164 | |
| 165 RenderWidgetCompositor::DidFailToInitializeOutputSurface(); | |
| 166 } | |
| 167 | |
| 168 void SetUp(bool use_null_output_surface, | |
| 169 int expected_failures, | |
| 170 int expected_successes, | |
| 171 int expected_fallback_succeses) { | |
| 172 use_null_output_surface_ = use_null_output_surface; | |
| 173 expected_failures_ = expected_failures; | |
| 174 expected_successes_ = expected_successes; | |
| 175 expected_fallback_successes_ = expected_fallback_succeses; | |
| 176 expected_requests_ = | |
| 177 expected_failures_ + expected_successes_ + expected_fallback_successes_; | |
| 178 } | |
| 179 | |
| 180 void EndTest() { base::MessageLoop::current()->Quit(); } | |
| 181 | |
| 182 void AfterTest() { | |
| 183 EXPECT_EQ(expected_failures_, num_failures_); | |
| 184 EXPECT_EQ(expected_successes_, num_successes_); | |
| 185 EXPECT_EQ(expected_fallback_successes_, num_fallback_successes_); | |
| 186 EXPECT_EQ(expected_requests_, num_requests_); | |
| 187 } | |
| 188 | |
| 189 private: | |
| 190 int expected_failures_; | |
| 191 int expected_successes_; | |
| 192 int expected_fallback_successes_; | |
| 193 int expected_requests_; | |
| 194 int num_requests_; | |
| 195 int num_requests_since_last_success_; | |
| 196 int num_successes_; | |
| 197 int num_fallback_successes_; | |
| 198 int num_failures_; | |
| 199 bool last_create_was_fallback_; | |
| 200 bool use_null_output_surface_; | |
| 201 | |
| 202 DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositorOutputSurface); | |
| 203 }; | |
| 204 | |
| 205 class RenderWidgetCompositorOutputSurfaceTest : public testing::Test { | |
| 206 public: | |
| 207 RenderWidgetCompositorOutputSurfaceTest() | |
| 208 : render_widget_(make_scoped_refptr(new RenderWidgetOutputSurface)), | |
| 209 render_widget_compositor_(make_scoped_ptr( | |
| 210 new RenderWidgetCompositorOutputSurface(render_widget_.get(), | |
| 211 false))) { | |
| 212 render_widget_->SetCompositor(render_widget_compositor_.get()); | |
| 213 } | |
| 214 | |
| 215 void RunTest(bool use_null_output_surface, | |
| 216 int expected_failures, | |
|
no sievers
2014/12/02 20:38:07
nit: should this be called |num_failures| or |num_
enne (OOO)
2014/12/02 21:09:33
num_failures_before_success sounds good. Done.
| |
| 217 int expected_successes, | |
| 218 int expected_fallback_succeses) { | |
| 219 render_widget_compositor_->SetUp(use_null_output_surface, expected_failures, | |
| 220 expected_successes, | |
| 221 expected_fallback_succeses); | |
| 222 base::MessageLoop::current()->PostTask( | |
| 223 FROM_HERE, | |
| 224 base::Bind(&RenderWidgetCompositor::RequestNewOutputSurface, | |
| 225 base::Unretained(render_widget_compositor_.get()))); | |
| 226 // TODO(enne): should probably add timeout logic | |
|
no sievers
2014/12/02 20:38:07
Hmm or maybe not? Don't the unit test harnesses pr
enne (OOO)
2014/12/02 21:09:33
Maybe they do on the bots? cc unit tests post a mo
| |
| 227 base::MessageLoop::current()->Run(); | |
| 228 render_widget_compositor_->AfterTest(); | |
| 229 } | |
| 230 | |
| 231 protected: | |
| 232 base::MessageLoop ye_olde_message_loope_; | |
| 233 MockRenderThread render_thread_; | |
| 234 scoped_refptr<RenderWidgetOutputSurface> render_widget_; | |
| 235 scoped_ptr<RenderWidgetCompositorOutputSurface> render_widget_compositor_; | |
| 236 | |
| 237 private: | |
| 238 DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositorOutputSurfaceTest); | |
| 239 }; | |
| 240 | |
| 241 scoped_ptr<cc::OutputSurface> RenderWidgetOutputSurface::CreateOutputSurface( | |
| 242 bool fallback) { | |
| 243 return compositor_->CreateOutputSurface(fallback); | |
| 244 } | |
| 245 | |
| 246 void RenderWidgetOutputSurface::SetCompositor( | |
| 247 RenderWidgetCompositorOutputSurface* compositor) { | |
| 248 compositor_ = compositor; | |
| 249 } | |
| 250 | |
| 251 TEST_F(RenderWidgetCompositorOutputSurfaceTest, SucceedOnce) { | |
| 252 RunTest(false, 0, 1, 0); | |
| 253 } | |
| 254 | |
| 255 TEST_F(RenderWidgetCompositorOutputSurfaceTest, SucceedTwice) { | |
| 256 RunTest(false, 0, 2, 0); | |
| 257 } | |
| 258 | |
| 259 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FailOnceNull) { | |
| 260 EXPECT_GT(RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK, 2); | |
|
no sievers
2014/12/02 20:38:07
nit: static_assert here and below
enne (OOO)
2014/12/02 21:09:33
Done.
| |
| 261 RunTest(true, 1, 1, 0); | |
| 262 } | |
| 263 | |
| 264 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FailOnceBind) { | |
| 265 EXPECT_GT(RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK, 2); | |
| 266 RunTest(false, 1, 1, 0); | |
| 267 } | |
| 268 | |
| 269 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FallbackSuccessNull) { | |
| 270 RunTest(true, RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK, | |
| 271 0, 1); | |
| 272 } | |
| 273 | |
| 274 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FallbackSuccessBind) { | |
| 275 RunTest(false, RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK, | |
| 276 0, 1); | |
| 277 } | |
| 278 | |
| 279 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FallbackSuccessNormalSuccess) { | |
| 280 // The first success is a fallback, but the next should not be a fallback. | |
| 281 RunTest(false, RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK, | |
| 282 1, 1); | |
| 283 } | |
| 284 | |
| 78 } // namespace content | 285 } // namespace content |
| OLD | NEW |