Close the password bubble when navigating between tabs.
[chromium-blink-merge.git] / cc / surfaces / surface_factory_unittest.cc
blob08156368c4c2bf628d16b1c7470ab17a7c9754a1
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 "cc/output/compositor_frame.h"
6 #include "cc/output/delegated_frame_data.h"
7 #include "cc/surfaces/surface.h"
8 #include "cc/surfaces/surface_factory.h"
9 #include "cc/surfaces/surface_factory_client.h"
10 #include "cc/surfaces/surface_manager.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gfx/size.h"
14 namespace cc {
15 namespace {
17 class TestSurfaceFactoryClient : public SurfaceFactoryClient {
18 public:
19 TestSurfaceFactoryClient() {}
20 virtual ~TestSurfaceFactoryClient() {}
22 virtual void ReturnResources(
23 const ReturnedResourceArray& resources) OVERRIDE {
24 returned_resources_.insert(
25 returned_resources_.end(), resources.begin(), resources.end());
28 const ReturnedResourceArray& returned_resources() const {
29 return returned_resources_;
32 void clear_returned_resources() { returned_resources_.clear(); }
34 private:
35 ReturnedResourceArray returned_resources_;
37 DISALLOW_COPY_AND_ASSIGN(TestSurfaceFactoryClient);
40 class SurfaceFactoryTest : public testing::Test {
41 public:
42 SurfaceFactoryTest() : factory_(&manager_, &client_), surface_id_(3) {
43 factory_.Create(surface_id_, gfx::Size(5, 5));
46 virtual ~SurfaceFactoryTest() { factory_.Destroy(surface_id_); }
48 void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids,
49 size_t num_resource_ids) {
50 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
51 for (size_t i = 0u; i < num_resource_ids; ++i) {
52 TransferableResource resource;
53 resource.id = resource_ids[i];
54 resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
55 frame_data->resource_list.push_back(resource);
57 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
58 frame->delegated_frame_data = frame_data.Pass();
59 factory_.SubmitFrame(surface_id_, frame.Pass(), base::Closure());
62 void UnrefResources(ResourceProvider::ResourceId* ids_to_unref,
63 int* counts_to_unref,
64 size_t num_ids_to_unref) {
65 ReturnedResourceArray unref_array;
66 for (size_t i = 0; i < num_ids_to_unref; ++i) {
67 ReturnedResource resource;
68 resource.id = ids_to_unref[i];
69 resource.count = counts_to_unref[i];
70 unref_array.push_back(resource);
72 factory_.UnrefResources(unref_array);
75 void CheckReturnedResourcesMatchExpected(
76 ResourceProvider::ResourceId* expected_returned_ids,
77 int* expected_returned_counts,
78 size_t expected_resources) {
79 const ReturnedResourceArray& actual_resources =
80 client_.returned_resources();
81 ASSERT_EQ(expected_resources, actual_resources.size());
82 for (size_t i = 0; i < expected_resources; ++i) {
83 ReturnedResource resource = actual_resources[i];
84 EXPECT_EQ(expected_returned_ids[i], resource.id);
85 EXPECT_EQ(expected_returned_counts[i], resource.count);
87 client_.clear_returned_resources();
90 void RefCurrentFrameResources() {
91 Surface* surface = manager_.GetSurfaceForId(surface_id_);
92 factory_.RefResources(
93 surface->GetEligibleFrame()->delegated_frame_data->resource_list);
96 protected:
97 SurfaceManager manager_;
98 TestSurfaceFactoryClient client_;
99 SurfaceFactory factory_;
100 SurfaceId surface_id_;
103 // Tests submitting a frame with resources followed by one with no resources
104 // with no resource provider action in between.
105 TEST_F(SurfaceFactoryTest, ResourceLifetimeSimple) {
106 ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3};
107 SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
109 // All of the resources submitted in the first frame are still in use at this
110 // time by virtue of being in the pending frame, so none can be returned to
111 // the client yet.
112 EXPECT_EQ(0u, client_.returned_resources().size());
113 client_.clear_returned_resources();
115 // The second frame references no resources and thus should make all resources
116 // available to be returned.
117 SubmitFrameWithResources(NULL, 0);
119 ResourceProvider::ResourceId expected_returned_ids[] = {1, 2, 3};
120 int expected_returned_counts[] = {1, 1, 1};
121 CheckReturnedResourcesMatchExpected(expected_returned_ids,
122 expected_returned_counts,
123 arraysize(expected_returned_counts));
126 // Tests submitting a frame with resources followed by one with no resources
127 // with the resource provider holding everything alive.
128 TEST_F(SurfaceFactoryTest, ResourceLifetimeSimpleWithProviderHoldingAlive) {
129 ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3};
130 SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
132 // All of the resources submitted in the first frame are still in use at this
133 // time by virtue of being in the pending frame, so none can be returned to
134 // the client yet.
135 EXPECT_EQ(0u, client_.returned_resources().size());
136 client_.clear_returned_resources();
138 // Hold on to everything.
139 RefCurrentFrameResources();
141 // The second frame references no resources and thus should make all resources
142 // available to be returned as soon as the resource provider releases them.
143 SubmitFrameWithResources(NULL, 0);
145 EXPECT_EQ(0u, client_.returned_resources().size());
146 client_.clear_returned_resources();
148 int release_counts[] = {1, 1, 1};
149 UnrefResources(first_frame_ids, release_counts, arraysize(first_frame_ids));
151 ResourceProvider::ResourceId expected_returned_ids[] = {1, 2, 3};
152 int expected_returned_counts[] = {1, 1, 1};
153 CheckReturnedResourcesMatchExpected(expected_returned_ids,
154 expected_returned_counts,
155 arraysize(expected_returned_counts));
158 // Tests referencing a resource, unref'ing it to zero, then using it again
159 // before returning it to the client.
160 TEST_F(SurfaceFactoryTest, ResourceReusedBeforeReturn) {
161 ResourceProvider::ResourceId first_frame_ids[] = {7};
162 SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
164 // This removes all references to resource id 7.
165 SubmitFrameWithResources(NULL, 0);
167 // This references id 7 again.
168 SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
170 // This removes it again.
171 SubmitFrameWithResources(NULL, 0);
173 // Now it should be returned.
174 // We don't care how many entries are in the returned array for 7, so long as
175 // the total returned count matches the submitted count.
176 const ReturnedResourceArray& returned = client_.returned_resources();
177 size_t return_count = 0;
178 for (size_t i = 0; i < returned.size(); ++i) {
179 EXPECT_EQ(7u, returned[i].id);
180 return_count += returned[i].count;
182 EXPECT_EQ(2u, return_count);
185 // Tests having resources referenced multiple times, as if referenced by
186 // multiple providers.
187 TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) {
188 ResourceProvider::ResourceId first_frame_ids[] = {3, 4};
189 SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
191 // Ref resources from the first frame twice.
192 RefCurrentFrameResources();
193 RefCurrentFrameResources();
195 ResourceProvider::ResourceId second_frame_ids[] = {4, 5};
196 SubmitFrameWithResources(second_frame_ids, arraysize(second_frame_ids));
198 // Ref resources from the second frame 3 times.
199 RefCurrentFrameResources();
200 RefCurrentFrameResources();
201 RefCurrentFrameResources();
203 // Submit a frame with no resources to remove all current frame refs from
204 // submitted resources.
205 SubmitFrameWithResources(NULL, 0);
207 EXPECT_EQ(0u, client_.returned_resources().size());
208 client_.clear_returned_resources();
210 // Expected current refs:
211 // 3 -> 2
212 // 4 -> 2 + 3 = 5
213 // 5 -> 3
215 SCOPED_TRACE("unref all 3");
216 ResourceProvider::ResourceId ids_to_unref[] = {3, 4, 5};
217 int counts[] = {1, 1, 1};
218 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
220 EXPECT_EQ(0u, client_.returned_resources().size());
221 client_.clear_returned_resources();
223 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
225 ResourceProvider::ResourceId expected_returned_ids[] = {3};
226 int expected_returned_counts[] = {1};
227 CheckReturnedResourcesMatchExpected(expected_returned_ids,
228 expected_returned_counts,
229 arraysize(expected_returned_counts));
232 // Expected refs remaining:
233 // 4 -> 3
234 // 5 -> 1
236 SCOPED_TRACE("unref 4 and 5");
237 ResourceProvider::ResourceId ids_to_unref[] = {4, 5};
238 int counts[] = {1, 1};
239 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
241 ResourceProvider::ResourceId expected_returned_ids[] = {5};
242 int expected_returned_counts[] = {1};
243 CheckReturnedResourcesMatchExpected(expected_returned_ids,
244 expected_returned_counts,
245 arraysize(expected_returned_counts));
248 // Now, just 2 refs remaining on resource 4. Unref both at once and make sure
249 // the returned count is correct.
251 SCOPED_TRACE("unref only 4");
252 ResourceProvider::ResourceId ids_to_unref[] = {4};
253 int counts[] = {2};
254 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
256 ResourceProvider::ResourceId expected_returned_ids[] = {4};
257 int expected_returned_counts[] = {2};
258 CheckReturnedResourcesMatchExpected(expected_returned_ids,
259 expected_returned_counts,
260 arraysize(expected_returned_counts));
264 TEST_F(SurfaceFactoryTest, ResourceLifetime) {
265 ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3};
266 SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
268 // All of the resources submitted in the first frame are still in use at this
269 // time by virtue of being in the pending frame, so none can be returned to
270 // the client yet.
271 EXPECT_EQ(0u, client_.returned_resources().size());
272 client_.clear_returned_resources();
274 // The second frame references some of the same resources, but some different
275 // ones. We expect to receive back resource 1 with a count of 1 since it was
276 // only referenced by the first frame.
277 ResourceProvider::ResourceId second_frame_ids[] = {2, 3, 4};
278 SubmitFrameWithResources(second_frame_ids, arraysize(second_frame_ids));
281 SCOPED_TRACE("second frame");
282 ResourceProvider::ResourceId expected_returned_ids[] = {1};
283 int expected_returned_counts[] = {1};
284 CheckReturnedResourcesMatchExpected(expected_returned_ids,
285 expected_returned_counts,
286 arraysize(expected_returned_counts));
289 // The third frame references a disjoint set of resources, so we expect to
290 // receive back all resources from the first and second frames. Resource IDs 2
291 // and 3 will have counts of 2, since they were used in both frames, and
292 // resource ID 4 will have a count of 1.
293 ResourceProvider::ResourceId third_frame_ids[] = {10, 11, 12, 13};
294 SubmitFrameWithResources(third_frame_ids, arraysize(third_frame_ids));
297 SCOPED_TRACE("third frame");
298 ResourceProvider::ResourceId expected_returned_ids[] = {2, 3, 4};
299 int expected_returned_counts[] = {2, 2, 1};
300 CheckReturnedResourcesMatchExpected(expected_returned_ids,
301 expected_returned_counts,
302 arraysize(expected_returned_counts));
305 // Simulate a ResourceProvider taking a ref on all of the resources.
306 RefCurrentFrameResources();
308 ResourceProvider::ResourceId fourth_frame_ids[] = {12, 13};
309 SubmitFrameWithResources(fourth_frame_ids, arraysize(fourth_frame_ids));
311 EXPECT_EQ(0u, client_.returned_resources().size());
313 RefCurrentFrameResources();
315 // All resources are still being used by the external reference, so none can
316 // be returned to the client.
317 EXPECT_EQ(0u, client_.returned_resources().size());
319 // Release resources associated with the first RefCurrentFrameResources() call
320 // first.
322 ResourceProvider::ResourceId ids_to_unref[] = {10, 11, 12, 13};
323 int counts[] = {1, 1, 1, 1};
324 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
328 SCOPED_TRACE("fourth frame, first unref");
329 ResourceProvider::ResourceId expected_returned_ids[] = {10, 11};
330 int expected_returned_counts[] = {1, 1};
331 CheckReturnedResourcesMatchExpected(expected_returned_ids,
332 expected_returned_counts,
333 arraysize(expected_returned_counts));
337 ResourceProvider::ResourceId ids_to_unref[] = {12, 13};
338 int counts[] = {1, 1};
339 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
342 // Resources 12 and 13 are still in use by the current frame, so they
343 // shouldn't be available to be returned.
344 EXPECT_EQ(0u, client_.returned_resources().size());
346 // If we submit an empty frame, however, they should become available.
347 SubmitFrameWithResources(NULL, 0u);
350 SCOPED_TRACE("fourth frame, second unref");
351 ResourceProvider::ResourceId expected_returned_ids[] = {12, 13};
352 int expected_returned_counts[] = {2, 2};
353 CheckReturnedResourcesMatchExpected(expected_returned_ids,
354 expected_returned_counts,
355 arraysize(expected_returned_counts));
359 } // namespace
360 } // namespace cc