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 14 namespace cc { 15 namespace { 16 17 class 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 92 TEST_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 114 TEST_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 140 TEST_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 198 TEST_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 240 TEST_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 284 TEST_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 333 TEST_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 348 TEST_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 373 TEST_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