delegated_frame_provider_unittest.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
1// Copyright 2013 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.
4
5#include "cc/layers/delegated_frame_provider.h"
6#include "cc/layers/delegated_frame_resource_collection.h"
7#include "cc/layers/delegated_renderer_layer.h"
8#include "cc/output/delegated_frame_data.h"
9#include "cc/quads/texture_draw_quad.h"
10#include "cc/resources/returned_resource.h"
11#include "cc/resources/transferable_resource.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace cc {
15namespace {
16
17class DelegatedFrameProviderTest
18    : public testing::Test,
19      public DelegatedFrameResourceCollectionClient {
20 protected:
21  DelegatedFrameProviderTest() : resources_available_(false) {}
22
23  scoped_ptr<DelegatedFrameData> CreateFrameData(gfx::Rect root_output_rect,
24                                                 gfx::Rect root_damage_rect) {
25    scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData);
26
27    scoped_ptr<RenderPass> root_pass(RenderPass::Create());
28    root_pass->SetNew(RenderPass::Id(1, 1),
29                      root_output_rect,
30                      root_damage_rect,
31                      gfx::Transform());
32    frame->render_pass_list.push_back(root_pass.Pass());
33    return frame.Pass();
34  }
35
36  void AddTransferableResource(DelegatedFrameData* frame,
37                               ResourceProvider::ResourceId resource_id) {
38    TransferableResource resource;
39    resource.id = resource_id;
40    resource.target = GL_TEXTURE_2D;
41    frame->resource_list.push_back(resource);
42  }
43
44  void AddTextureQuad(DelegatedFrameData* frame,
45                      ResourceProvider::ResourceId resource_id) {
46    scoped_ptr<SharedQuadState> sqs = SharedQuadState::Create();
47    scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
48    float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f};
49    quad->SetNew(sqs.get(),
50                 gfx::Rect(0, 0, 10, 10),
51                 gfx::Rect(0, 0, 10, 10),
52                 resource_id,
53                 false,
54                 gfx::PointF(0.f, 0.f),
55                 gfx::PointF(1.f, 1.f),
56                 SK_ColorTRANSPARENT,
57                 vertex_opacity,
58                 false);
59    frame->render_pass_list[0]->shared_quad_state_list.push_back(sqs.Pass());
60    frame->render_pass_list[0]->quad_list.push_back(quad.PassAs<DrawQuad>());
61  }
62
63  virtual void SetUp() OVERRIDE {
64    resource_collection_ = new DelegatedFrameResourceCollection;
65    resource_collection_->SetClient(this);
66  }
67
68  virtual void TearDown() OVERRIDE { resource_collection_->SetClient(NULL); }
69
70  virtual void UnusedResourcesAreAvailable() OVERRIDE {
71    resources_available_ = true;
72    resource_collection_->TakeUnusedResourcesForChildCompositor(&resources_);
73  }
74
75  bool ReturnAndResetResourcesAvailable() {
76    bool r = resources_available_;
77    resources_available_ = false;
78    return r;
79  }
80
81  void SetFrameProvider(scoped_ptr<DelegatedFrameData> frame_data) {
82    frame_provider_ =
83        new DelegatedFrameProvider(resource_collection_, frame_data.Pass());
84  }
85
86  scoped_refptr<DelegatedFrameResourceCollection> resource_collection_;
87  scoped_refptr<DelegatedFrameProvider> frame_provider_;
88  bool resources_available_;
89  ReturnedResourceArray resources_;
90};
91
92TEST_F(DelegatedFrameProviderTest, SameResources) {
93  scoped_ptr<DelegatedFrameData> frame =
94      CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
95  AddTextureQuad(frame.get(), 444);
96  AddTransferableResource(frame.get(), 444);
97  SetFrameProvider(frame.Pass());
98
99  frame = CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
100  AddTextureQuad(frame.get(), 444);
101  AddTransferableResource(frame.get(), 444);
102  SetFrameProvider(frame.Pass());
103
104  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
105  EXPECT_EQ(0u, resources_.size());
106
107  frame_provider_ = NULL;
108
109  EXPECT_TRUE(ReturnAndResetResourcesAvailable());
110  EXPECT_EQ(1u, resources_.size());
111  EXPECT_EQ(444u, resources_[0].id);
112}
113
114TEST_F(DelegatedFrameProviderTest, ReplaceResources) {
115  scoped_ptr<DelegatedFrameData> frame =
116      CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
117  AddTextureQuad(frame.get(), 444);
118  AddTransferableResource(frame.get(), 444);
119  SetFrameProvider(frame.Pass());
120
121  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
122
123  frame = CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
124  AddTextureQuad(frame.get(), 555);
125  AddTransferableResource(frame.get(), 555);
126  SetFrameProvider(frame.Pass());
127
128  EXPECT_TRUE(ReturnAndResetResourcesAvailable());
129  EXPECT_EQ(1u, resources_.size());
130  EXPECT_EQ(444u, resources_[0].id);
131  resources_.clear();
132
133  frame_provider_ = NULL;
134
135  EXPECT_TRUE(ReturnAndResetResourcesAvailable());
136  EXPECT_EQ(1u, resources_.size());
137  EXPECT_EQ(555u, resources_[0].id);
138}
139
140TEST_F(DelegatedFrameProviderTest, RefResources) {
141  scoped_ptr<DelegatedFrameData> frame =
142      CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
143  AddTextureQuad(frame.get(), 444);
144  AddTransferableResource(frame.get(), 444);
145
146  TransferableResourceArray reffed = frame->resource_list;
147  ReturnedResourceArray returned;
148  TransferableResource::ReturnResources(reffed, &returned);
149
150  SetFrameProvider(frame.Pass());
151
152  scoped_refptr<DelegatedRendererLayer> observer1 =
153      DelegatedRendererLayer::Create(frame_provider_);
154  scoped_refptr<DelegatedRendererLayer> observer2 =
155      DelegatedRendererLayer::Create(frame_provider_);
156
157  gfx::RectF damage;
158
159  // Both observers get a full frame of damage on the first request.
160  frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
161  EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
162  frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
163  EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
164
165  // And both get no damage on the 2nd request. This adds a second ref to the
166  // resources.
167  frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
168  EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
169  frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
170  EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
171
172  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
173
174  frame = CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
175  AddTextureQuad(frame.get(), 555);
176  AddTransferableResource(frame.get(), 555);
177  frame_provider_->SetFrameData(frame.Pass());
178
179  // The resources from the first frame are still reffed by the observers.
180  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
181
182  // There are 4 refs taken.
183  frame_provider_->UnrefResourcesOnMainThread(returned);
184  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
185  frame_provider_->UnrefResourcesOnMainThread(returned);
186  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
187  frame_provider_->UnrefResourcesOnMainThread(returned);
188  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
189
190  // The 4th unref will release them.
191  frame_provider_->UnrefResourcesOnMainThread(returned);
192
193  EXPECT_TRUE(ReturnAndResetResourcesAvailable());
194  EXPECT_EQ(1u, resources_.size());
195  EXPECT_EQ(444u, resources_[0].id);
196}
197
198TEST_F(DelegatedFrameProviderTest, RefResourcesInFrameProvider) {
199  scoped_ptr<DelegatedFrameData> frame =
200      CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
201  AddTextureQuad(frame.get(), 444);
202  AddTransferableResource(frame.get(), 444);
203
204  TransferableResourceArray reffed = frame->resource_list;
205  ReturnedResourceArray returned;
206  TransferableResource::ReturnResources(reffed, &returned);
207
208  SetFrameProvider(frame.Pass());
209
210  scoped_refptr<DelegatedRendererLayer> observer1 =
211      DelegatedRendererLayer::Create(frame_provider_);
212  scoped_refptr<DelegatedRendererLayer> observer2 =
213      DelegatedRendererLayer::Create(frame_provider_);
214
215  gfx::RectF damage;
216
217  // Take a ref on each observer.
218  frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
219  frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
220
221  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
222
223  // Release both refs. But there's still a ref held in the frame
224  // provider itself.
225  frame_provider_->UnrefResourcesOnMainThread(returned);
226  frame_provider_->UnrefResourcesOnMainThread(returned);
227  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
228
229  // Setting a new frame will release it.
230  frame = CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
231  AddTextureQuad(frame.get(), 555);
232  AddTransferableResource(frame.get(), 555);
233  frame_provider_->SetFrameData(frame.Pass());
234
235  EXPECT_TRUE(ReturnAndResetResourcesAvailable());
236  EXPECT_EQ(1u, resources_.size());
237  EXPECT_EQ(444u, resources_[0].id);
238}
239
240TEST_F(DelegatedFrameProviderTest, RefResourcesInFrameProviderUntilDestroy) {
241  scoped_ptr<DelegatedFrameData> frame =
242      CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
243  AddTextureQuad(frame.get(), 444);
244  AddTransferableResource(frame.get(), 444);
245
246  TransferableResourceArray reffed = frame->resource_list;
247  ReturnedResourceArray returned;
248  TransferableResource::ReturnResources(reffed, &returned);
249
250  SetFrameProvider(frame.Pass());
251
252  scoped_refptr<DelegatedRendererLayer> observer1 =
253      DelegatedRendererLayer::Create(frame_provider_);
254  scoped_refptr<DelegatedRendererLayer> observer2 =
255      DelegatedRendererLayer::Create(frame_provider_);
256
257  gfx::RectF damage;
258
259  // Take a ref on each observer.
260  frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
261  frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
262
263  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
264
265  // Release both refs. But there's still a ref held in the frame
266  // provider itself.
267  frame_provider_->UnrefResourcesOnMainThread(returned);
268  frame_provider_->UnrefResourcesOnMainThread(returned);
269  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
270
271  // Releasing all references to the frame provider will release
272  // the frame.
273  observer1 = NULL;
274  observer2 = NULL;
275  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
276
277  frame_provider_ = NULL;
278
279  EXPECT_TRUE(ReturnAndResetResourcesAvailable());
280  EXPECT_EQ(1u, resources_.size());
281  EXPECT_EQ(444u, resources_[0].id);
282}
283
284TEST_F(DelegatedFrameProviderTest, Damage) {
285  scoped_ptr<DelegatedFrameData> frame =
286      CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
287  AddTextureQuad(frame.get(), 444);
288  AddTransferableResource(frame.get(), 444);
289
290  TransferableResourceArray reffed = frame->resource_list;
291  ReturnedResourceArray returned;
292  TransferableResource::ReturnResources(reffed, &returned);
293
294  SetFrameProvider(frame.Pass());
295
296  scoped_refptr<DelegatedRendererLayer> observer1 =
297      DelegatedRendererLayer::Create(frame_provider_);
298  scoped_refptr<DelegatedRendererLayer> observer2 =
299      DelegatedRendererLayer::Create(frame_provider_);
300
301  gfx::RectF damage;
302
303  // Both observers get a full frame of damage on the first request.
304  frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
305  EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
306  frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
307  EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
308
309  // And both get no damage on the 2nd request.
310  frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
311  EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
312  frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
313  EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
314
315  frame = CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
316  AddTextureQuad(frame.get(), 555);
317  AddTransferableResource(frame.get(), 555);
318  frame_provider_->SetFrameData(frame.Pass());
319
320  // Both observers get the damage for the new frame.
321  frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
322  EXPECT_EQ(gfx::RectF(2.f, 2.f).ToString(), damage.ToString());
323  frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
324  EXPECT_EQ(gfx::RectF(2.f, 2.f).ToString(), damage.ToString());
325
326  // And both get no damage on the 2nd request.
327  frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
328  EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
329  frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
330  EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
331}
332
333TEST_F(DelegatedFrameProviderTest, LostNothing) {
334  scoped_ptr<DelegatedFrameData> frame =
335      CreateFrameData(gfx::Rect(5, 5), gfx::Rect(5, 5));
336
337  TransferableResourceArray reffed = frame->resource_list;
338
339  SetFrameProvider(frame.Pass());
340
341  // There is nothing to lose.
342  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
343  EXPECT_FALSE(resource_collection_->LoseAllResources());
344  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
345  EXPECT_EQ(0u, resources_.size());
346}
347
348TEST_F(DelegatedFrameProviderTest, LostSomething) {
349  scoped_ptr<DelegatedFrameData> frame =
350      CreateFrameData(gfx::Rect(5, 5), gfx::Rect(5, 5));
351  AddTextureQuad(frame.get(), 444);
352  AddTransferableResource(frame.get(), 444);
353
354  SetFrameProvider(frame.Pass());
355
356  // Add a second reference on the resource.
357  frame = CreateFrameData(gfx::Rect(5, 5), gfx::Rect(5, 5));
358  AddTextureQuad(frame.get(), 444);
359  AddTransferableResource(frame.get(), 444);
360
361  SetFrameProvider(frame.Pass());
362
363  // There is something to lose.
364  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
365  EXPECT_TRUE(resource_collection_->LoseAllResources());
366  EXPECT_TRUE(ReturnAndResetResourcesAvailable());
367
368  EXPECT_EQ(1u, resources_.size());
369  EXPECT_EQ(444u, resources_[0].id);
370  EXPECT_EQ(2, resources_[0].count);
371}
372
373TEST_F(DelegatedFrameProviderTest, NothingReturnedAfterLoss) {
374  scoped_ptr<DelegatedFrameData> frame =
375      CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
376  AddTextureQuad(frame.get(), 444);
377  AddTransferableResource(frame.get(), 444);
378  SetFrameProvider(frame.Pass());
379
380  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
381
382  // Lose all the resources.
383  EXPECT_TRUE(resource_collection_->LoseAllResources());
384  EXPECT_TRUE(ReturnAndResetResourcesAvailable());
385  resources_.clear();
386
387  frame_provider_ = NULL;
388
389  // Nothing is returned twice.
390  EXPECT_FALSE(ReturnAndResetResourcesAvailable());
391  EXPECT_EQ(0u, resources_.size());
392}
393
394}  // namespace
395}  // namespace cc
396