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