Change DtmfSenderHandler to handle events on the signaling thread.
[chromium-blink-merge.git] / cc / surfaces / surface_factory_unittest.cc
blobe36636c5f1c28438777e7c536bae4c5b887be2df
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/geometry/size.h"
14 namespace cc {
15 namespace {
17 class TestSurfaceFactoryClient : public SurfaceFactoryClient {
18 public:
19 TestSurfaceFactoryClient() {}
20 ~TestSurfaceFactoryClient() override {}
22 void ReturnResources(const ReturnedResourceArray& resources) override {
23 returned_resources_.insert(
24 returned_resources_.end(), resources.begin(), resources.end());
27 const ReturnedResourceArray& returned_resources() const {
28 return returned_resources_;
31 void clear_returned_resources() { returned_resources_.clear(); }
33 private:
34 ReturnedResourceArray returned_resources_;
36 DISALLOW_COPY_AND_ASSIGN(TestSurfaceFactoryClient);
39 class SurfaceFactoryTest : public testing::Test {
40 public:
41 SurfaceFactoryTest() : factory_(&manager_, &client_), surface_id_(3) {
42 factory_.Create(surface_id_, gfx::Size(5, 5));
45 virtual ~SurfaceFactoryTest() {
46 if (!surface_id_.is_null())
47 factory_.Destroy(surface_id_);
50 void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids,
51 size_t num_resource_ids) {
52 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
53 for (size_t i = 0u; i < num_resource_ids; ++i) {
54 TransferableResource resource;
55 resource.id = resource_ids[i];
56 resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
57 frame_data->resource_list.push_back(resource);
59 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
60 frame->delegated_frame_data = frame_data.Pass();
61 factory_.SubmitFrame(surface_id_, frame.Pass(), base::Closure());
64 void UnrefResources(ResourceProvider::ResourceId* ids_to_unref,
65 int* counts_to_unref,
66 size_t num_ids_to_unref) {
67 ReturnedResourceArray unref_array;
68 for (size_t i = 0; i < num_ids_to_unref; ++i) {
69 ReturnedResource resource;
70 resource.id = ids_to_unref[i];
71 resource.count = counts_to_unref[i];
72 unref_array.push_back(resource);
74 factory_.UnrefResources(unref_array);
77 void CheckReturnedResourcesMatchExpected(
78 ResourceProvider::ResourceId* expected_returned_ids,
79 int* expected_returned_counts,
80 size_t expected_resources) {
81 const ReturnedResourceArray& actual_resources =
82 client_.returned_resources();
83 ASSERT_EQ(expected_resources, actual_resources.size());
84 for (size_t i = 0; i < expected_resources; ++i) {
85 ReturnedResource resource = actual_resources[i];
86 EXPECT_EQ(expected_returned_ids[i], resource.id);
87 EXPECT_EQ(expected_returned_counts[i], resource.count);
89 client_.clear_returned_resources();
92 void RefCurrentFrameResources() {
93 Surface* surface = manager_.GetSurfaceForId(surface_id_);
94 factory_.RefResources(
95 surface->GetEligibleFrame()->delegated_frame_data->resource_list);
98 protected:
99 SurfaceManager manager_;
100 TestSurfaceFactoryClient client_;
101 SurfaceFactory factory_;
102 SurfaceId surface_id_;
105 // Tests submitting a frame with resources followed by one with no resources
106 // with no resource provider action in between.
107 TEST_F(SurfaceFactoryTest, ResourceLifetimeSimple) {
108 ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3};
109 SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
111 // All of the resources submitted in the first frame are still in use at this
112 // time by virtue of being in the pending frame, so none can be returned to
113 // the client yet.
114 EXPECT_EQ(0u, client_.returned_resources().size());
115 client_.clear_returned_resources();
117 // The second frame references no resources and thus should make all resources
118 // available to be returned.
119 SubmitFrameWithResources(NULL, 0);
121 ResourceProvider::ResourceId expected_returned_ids[] = {1, 2, 3};
122 int expected_returned_counts[] = {1, 1, 1};
123 CheckReturnedResourcesMatchExpected(expected_returned_ids,
124 expected_returned_counts,
125 arraysize(expected_returned_counts));
128 // Tests submitting a frame with resources followed by one with no resources
129 // with the resource provider holding everything alive.
130 TEST_F(SurfaceFactoryTest, ResourceLifetimeSimpleWithProviderHoldingAlive) {
131 ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3};
132 SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
134 // All of the resources submitted in the first frame are still in use at this
135 // time by virtue of being in the pending frame, so none can be returned to
136 // the client yet.
137 EXPECT_EQ(0u, client_.returned_resources().size());
138 client_.clear_returned_resources();
140 // Hold on to everything.
141 RefCurrentFrameResources();
143 // The second frame references no resources and thus should make all resources
144 // available to be returned as soon as the resource provider releases them.
145 SubmitFrameWithResources(NULL, 0);
147 EXPECT_EQ(0u, client_.returned_resources().size());
148 client_.clear_returned_resources();
150 int release_counts[] = {1, 1, 1};
151 UnrefResources(first_frame_ids, release_counts, arraysize(first_frame_ids));
153 ResourceProvider::ResourceId expected_returned_ids[] = {1, 2, 3};
154 int expected_returned_counts[] = {1, 1, 1};
155 CheckReturnedResourcesMatchExpected(expected_returned_ids,
156 expected_returned_counts,
157 arraysize(expected_returned_counts));
160 // Tests referencing a resource, unref'ing it to zero, then using it again
161 // before returning it to the client.
162 TEST_F(SurfaceFactoryTest, ResourceReusedBeforeReturn) {
163 ResourceProvider::ResourceId first_frame_ids[] = {7};
164 SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
166 // This removes all references to resource id 7.
167 SubmitFrameWithResources(NULL, 0);
169 // This references id 7 again.
170 SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
172 // This removes it again.
173 SubmitFrameWithResources(NULL, 0);
175 // Now it should be returned.
176 // We don't care how many entries are in the returned array for 7, so long as
177 // the total returned count matches the submitted count.
178 const ReturnedResourceArray& returned = client_.returned_resources();
179 size_t return_count = 0;
180 for (size_t i = 0; i < returned.size(); ++i) {
181 EXPECT_EQ(7u, returned[i].id);
182 return_count += returned[i].count;
184 EXPECT_EQ(2u, return_count);
187 // Tests having resources referenced multiple times, as if referenced by
188 // multiple providers.
189 TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) {
190 ResourceProvider::ResourceId first_frame_ids[] = {3, 4};
191 SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
193 // Ref resources from the first frame twice.
194 RefCurrentFrameResources();
195 RefCurrentFrameResources();
197 ResourceProvider::ResourceId second_frame_ids[] = {4, 5};
198 SubmitFrameWithResources(second_frame_ids, arraysize(second_frame_ids));
200 // Ref resources from the second frame 3 times.
201 RefCurrentFrameResources();
202 RefCurrentFrameResources();
203 RefCurrentFrameResources();
205 // Submit a frame with no resources to remove all current frame refs from
206 // submitted resources.
207 SubmitFrameWithResources(NULL, 0);
209 EXPECT_EQ(0u, client_.returned_resources().size());
210 client_.clear_returned_resources();
212 // Expected current refs:
213 // 3 -> 2
214 // 4 -> 2 + 3 = 5
215 // 5 -> 3
217 SCOPED_TRACE("unref all 3");
218 ResourceProvider::ResourceId ids_to_unref[] = {3, 4, 5};
219 int counts[] = {1, 1, 1};
220 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
222 EXPECT_EQ(0u, client_.returned_resources().size());
223 client_.clear_returned_resources();
225 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
227 ResourceProvider::ResourceId expected_returned_ids[] = {3};
228 int expected_returned_counts[] = {1};
229 CheckReturnedResourcesMatchExpected(expected_returned_ids,
230 expected_returned_counts,
231 arraysize(expected_returned_counts));
234 // Expected refs remaining:
235 // 4 -> 3
236 // 5 -> 1
238 SCOPED_TRACE("unref 4 and 5");
239 ResourceProvider::ResourceId ids_to_unref[] = {4, 5};
240 int counts[] = {1, 1};
241 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
243 ResourceProvider::ResourceId expected_returned_ids[] = {5};
244 int expected_returned_counts[] = {1};
245 CheckReturnedResourcesMatchExpected(expected_returned_ids,
246 expected_returned_counts,
247 arraysize(expected_returned_counts));
250 // Now, just 2 refs remaining on resource 4. Unref both at once and make sure
251 // the returned count is correct.
253 SCOPED_TRACE("unref only 4");
254 ResourceProvider::ResourceId ids_to_unref[] = {4};
255 int counts[] = {2};
256 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
258 ResourceProvider::ResourceId expected_returned_ids[] = {4};
259 int expected_returned_counts[] = {2};
260 CheckReturnedResourcesMatchExpected(expected_returned_ids,
261 expected_returned_counts,
262 arraysize(expected_returned_counts));
266 TEST_F(SurfaceFactoryTest, ResourceLifetime) {
267 ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3};
268 SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
270 // All of the resources submitted in the first frame are still in use at this
271 // time by virtue of being in the pending frame, so none can be returned to
272 // the client yet.
273 EXPECT_EQ(0u, client_.returned_resources().size());
274 client_.clear_returned_resources();
276 // The second frame references some of the same resources, but some different
277 // ones. We expect to receive back resource 1 with a count of 1 since it was
278 // only referenced by the first frame.
279 ResourceProvider::ResourceId second_frame_ids[] = {2, 3, 4};
280 SubmitFrameWithResources(second_frame_ids, arraysize(second_frame_ids));
283 SCOPED_TRACE("second frame");
284 ResourceProvider::ResourceId expected_returned_ids[] = {1};
285 int expected_returned_counts[] = {1};
286 CheckReturnedResourcesMatchExpected(expected_returned_ids,
287 expected_returned_counts,
288 arraysize(expected_returned_counts));
291 // The third frame references a disjoint set of resources, so we expect to
292 // receive back all resources from the first and second frames. Resource IDs 2
293 // and 3 will have counts of 2, since they were used in both frames, and
294 // resource ID 4 will have a count of 1.
295 ResourceProvider::ResourceId third_frame_ids[] = {10, 11, 12, 13};
296 SubmitFrameWithResources(third_frame_ids, arraysize(third_frame_ids));
299 SCOPED_TRACE("third frame");
300 ResourceProvider::ResourceId expected_returned_ids[] = {2, 3, 4};
301 int expected_returned_counts[] = {2, 2, 1};
302 CheckReturnedResourcesMatchExpected(expected_returned_ids,
303 expected_returned_counts,
304 arraysize(expected_returned_counts));
307 // Simulate a ResourceProvider taking a ref on all of the resources.
308 RefCurrentFrameResources();
310 ResourceProvider::ResourceId fourth_frame_ids[] = {12, 13};
311 SubmitFrameWithResources(fourth_frame_ids, arraysize(fourth_frame_ids));
313 EXPECT_EQ(0u, client_.returned_resources().size());
315 RefCurrentFrameResources();
317 // All resources are still being used by the external reference, so none can
318 // be returned to the client.
319 EXPECT_EQ(0u, client_.returned_resources().size());
321 // Release resources associated with the first RefCurrentFrameResources() call
322 // first.
324 ResourceProvider::ResourceId ids_to_unref[] = {10, 11, 12, 13};
325 int counts[] = {1, 1, 1, 1};
326 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
330 SCOPED_TRACE("fourth frame, first unref");
331 ResourceProvider::ResourceId expected_returned_ids[] = {10, 11};
332 int expected_returned_counts[] = {1, 1};
333 CheckReturnedResourcesMatchExpected(expected_returned_ids,
334 expected_returned_counts,
335 arraysize(expected_returned_counts));
339 ResourceProvider::ResourceId ids_to_unref[] = {12, 13};
340 int counts[] = {1, 1};
341 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
344 // Resources 12 and 13 are still in use by the current frame, so they
345 // shouldn't be available to be returned.
346 EXPECT_EQ(0u, client_.returned_resources().size());
348 // If we submit an empty frame, however, they should become available.
349 SubmitFrameWithResources(NULL, 0u);
352 SCOPED_TRACE("fourth frame, second unref");
353 ResourceProvider::ResourceId expected_returned_ids[] = {12, 13};
354 int expected_returned_counts[] = {2, 2};
355 CheckReturnedResourcesMatchExpected(expected_returned_ids,
356 expected_returned_counts,
357 arraysize(expected_returned_counts));
361 // Tests doing a DestroyAll before shutting down the factory;
362 TEST_F(SurfaceFactoryTest, DestroyAll) {
363 SurfaceId id(7);
364 factory_.Create(id, gfx::Size(1, 1));
366 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
367 TransferableResource resource;
368 resource.id = 1;
369 resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
370 frame_data->resource_list.push_back(resource);
371 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
372 frame->delegated_frame_data = frame_data.Pass();
373 factory_.SubmitFrame(id, frame.Pass(), base::Closure());
375 surface_id_ = SurfaceId();
376 factory_.DestroyAll();
379 TEST_F(SurfaceFactoryTest, DestroySequence) {
380 SurfaceId id2(5);
381 factory_.Create(id2, gfx::Size(5, 5));
383 // Check that waiting before the sequence is satisfied works.
384 std::set<SurfaceSequence> sequence;
385 sequence.insert(SurfaceSequence(0, 4));
386 factory_.DestroyOnSequence(id2, sequence);
388 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
389 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
390 frame->metadata.satisfies_sequences.push_back(6);
391 frame->metadata.satisfies_sequences.push_back(4);
392 frame->delegated_frame_data = frame_data.Pass();
393 DCHECK(manager_.GetSurfaceForId(id2));
394 factory_.SubmitFrame(surface_id_, frame.Pass(), base::Closure());
395 DCHECK(!manager_.GetSurfaceForId(id2));
397 // Check that waiting after the sequence is satisfied works.
398 factory_.Create(id2, gfx::Size(5, 5));
399 sequence.clear();
400 sequence.insert(SurfaceSequence(0, 6));
401 DCHECK(manager_.GetSurfaceForId(id2));
402 factory_.DestroyOnSequence(id2, sequence);
403 DCHECK(!manager_.GetSurfaceForId(id2));
406 } // namespace
407 } // namespace cc