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