| 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 num_failures_before_success_(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_ >= num_failures_before_success_; |
| 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 num_failures_before_success, |
| 170 int expected_successes, |
| 171 int expected_fallback_succeses) { |
| 172 use_null_output_surface_ = use_null_output_surface; |
| 173 num_failures_before_success_ = num_failures_before_success; |
| 174 expected_successes_ = expected_successes; |
| 175 expected_fallback_successes_ = expected_fallback_succeses; |
| 176 expected_requests_ = num_failures_before_success_ + expected_successes_ + |
| 177 expected_fallback_successes_; |
| 178 } |
| 179 |
| 180 void EndTest() { base::MessageLoop::current()->Quit(); } |
| 181 |
| 182 void AfterTest() { |
| 183 EXPECT_EQ(num_failures_before_success_, 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 num_failures_before_success_; |
| 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 num_failures_before_success, |
| 217 int expected_successes, |
| 218 int expected_fallback_succeses) { |
| 219 render_widget_compositor_->SetUp( |
| 220 use_null_output_surface, num_failures_before_success, |
| 221 expected_successes, expected_fallback_succeses); |
| 222 base::MessageLoop::current()->PostTask( |
| 223 FROM_HERE, |
| 224 base::Bind(&RenderWidgetCompositor::RequestNewOutputSurface, |
| 225 base::Unretained(render_widget_compositor_.get()))); |
| 226 base::MessageLoop::current()->Run(); |
| 227 render_widget_compositor_->AfterTest(); |
| 228 } |
| 229 |
| 230 protected: |
| 231 base::MessageLoop ye_olde_message_loope_; |
| 232 MockRenderThread render_thread_; |
| 233 scoped_refptr<RenderWidgetOutputSurface> render_widget_; |
| 234 scoped_ptr<RenderWidgetCompositorOutputSurface> render_widget_compositor_; |
| 235 |
| 236 private: |
| 237 DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositorOutputSurfaceTest); |
| 238 }; |
| 239 |
| 240 scoped_ptr<cc::OutputSurface> RenderWidgetOutputSurface::CreateOutputSurface( |
| 241 bool fallback) { |
| 242 return compositor_->CreateOutputSurface(fallback); |
| 243 } |
| 244 |
| 245 void RenderWidgetOutputSurface::SetCompositor( |
| 246 RenderWidgetCompositorOutputSurface* compositor) { |
| 247 compositor_ = compositor; |
| 248 } |
| 249 |
| 250 TEST_F(RenderWidgetCompositorOutputSurfaceTest, SucceedOnce) { |
| 251 RunTest(false, 0, 1, 0); |
| 252 } |
| 253 |
| 254 TEST_F(RenderWidgetCompositorOutputSurfaceTest, SucceedTwice) { |
| 255 RunTest(false, 0, 2, 0); |
| 256 } |
| 257 |
| 258 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FailOnceNull) { |
| 259 static_assert( |
| 260 RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK >= 2, |
| 261 "Adjust the values of this test if this fails"); |
| 262 RunTest(true, 1, 1, 0); |
| 263 } |
| 264 |
| 265 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FailOnceBind) { |
| 266 static_assert( |
| 267 RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK >= 2, |
| 268 "Adjust the values of this test if this fails"); |
| 269 RunTest(false, 1, 1, 0); |
| 270 } |
| 271 |
| 272 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FallbackSuccessNull) { |
| 273 RunTest(true, RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK, |
| 274 0, 1); |
| 275 } |
| 276 |
| 277 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FallbackSuccessBind) { |
| 278 RunTest(false, RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK, |
| 279 0, 1); |
| 280 } |
| 281 |
| 282 TEST_F(RenderWidgetCompositorOutputSurfaceTest, FallbackSuccessNormalSuccess) { |
| 283 // The first success is a fallback, but the next should not be a fallback. |
| 284 RunTest(false, RenderWidgetCompositor::OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK, |
| 285 1, 1); |
| 286 } |
| 287 |
| 78 } // namespace content | 288 } // namespace content |
| OLD | NEW |