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