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