GPU workaround to simulate Out of Memory errors with large textures
[chromium-blink-merge.git] / cc / layers / delegated_frame_provider_unittest.cc
blobfe8117e797a452d3bd30224434633f4101964d02
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.
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"
14 namespace cc {
15 namespace {
17 class DelegatedFrameProviderTest
18 : public testing::Test,
19 public DelegatedFrameResourceCollectionClient {
20 protected:
21 DelegatedFrameProviderTest() : resources_available_(false) {}
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);
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();
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);
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);
66 void SetUp() override {
67 resource_collection_ = new DelegatedFrameResourceCollection;
68 resource_collection_->SetClient(this);
71 void TearDown() override { resource_collection_->SetClient(nullptr); }
73 void UnusedResourcesAreAvailable() override {
74 resources_available_ = true;
75 resource_collection_->TakeUnusedResourcesForChildCompositor(&resources_);
78 bool ReturnAndResetResourcesAvailable() {
79 bool r = resources_available_;
80 resources_available_ = false;
81 return r;
84 void SetFrameProvider(scoped_ptr<DelegatedFrameData> frame_data) {
85 frame_provider_ =
86 new DelegatedFrameProvider(resource_collection_, frame_data.Pass());
89 scoped_refptr<DelegatedFrameResourceCollection> resource_collection_;
90 scoped_refptr<DelegatedFrameProvider> frame_provider_;
91 bool resources_available_;
92 ReturnedResourceArray resources_;
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());
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());
107 EXPECT_FALSE(ReturnAndResetResourcesAvailable());
108 EXPECT_EQ(0u, resources_.size());
110 frame_provider_ = nullptr;
112 EXPECT_TRUE(ReturnAndResetResourcesAvailable());
113 EXPECT_EQ(1u, resources_.size());
114 EXPECT_EQ(444u, resources_[0].id);
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());
124 EXPECT_FALSE(ReturnAndResetResourcesAvailable());
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());
131 EXPECT_TRUE(ReturnAndResetResourcesAvailable());
132 EXPECT_EQ(1u, resources_.size());
133 EXPECT_EQ(444u, resources_[0].id);
134 resources_.clear();
136 frame_provider_ = nullptr;
138 EXPECT_TRUE(ReturnAndResetResourcesAvailable());
139 EXPECT_EQ(1u, resources_.size());
140 EXPECT_EQ(555u, resources_[0].id);
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);
149 TransferableResourceArray reffed = frame->resource_list;
150 ReturnedResourceArray returned;
151 TransferableResource::ReturnResources(reffed, &returned);
153 SetFrameProvider(frame.Pass());
155 scoped_refptr<DelegatedRendererLayer> observer1 =
156 DelegatedRendererLayer::Create(frame_provider_);
157 scoped_refptr<DelegatedRendererLayer> observer2 =
158 DelegatedRendererLayer::Create(frame_provider_);
160 gfx::RectF damage;
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());
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());
175 EXPECT_FALSE(ReturnAndResetResourcesAvailable());
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());
182 // The resources from the first frame are still reffed by the observers.
183 EXPECT_FALSE(ReturnAndResetResourcesAvailable());
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());
193 // The 4th unref will release them.
194 frame_provider_->UnrefResourcesOnMainThread(returned);
196 EXPECT_TRUE(ReturnAndResetResourcesAvailable());
197 EXPECT_EQ(1u, resources_.size());
198 EXPECT_EQ(444u, resources_[0].id);
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);
207 TransferableResourceArray reffed = frame->resource_list;
208 ReturnedResourceArray returned;
209 TransferableResource::ReturnResources(reffed, &returned);
211 SetFrameProvider(frame.Pass());
213 scoped_refptr<DelegatedRendererLayer> observer1 =
214 DelegatedRendererLayer::Create(frame_provider_);
215 scoped_refptr<DelegatedRendererLayer> observer2 =
216 DelegatedRendererLayer::Create(frame_provider_);
218 gfx::RectF damage;
220 // Take a ref on each observer.
221 frame_provider_->GetFrameDataAndRefResources(observer1.get(), &damage);
222 frame_provider_->GetFrameDataAndRefResources(observer2.get(), &damage);
224 EXPECT_FALSE(ReturnAndResetResourcesAvailable());
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());
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());
238 EXPECT_TRUE(ReturnAndResetResourcesAvailable());
239 EXPECT_EQ(1u, resources_.size());
240 EXPECT_EQ(444u, resources_[0].id);
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);
249 TransferableResourceArray reffed = frame->resource_list;
250 ReturnedResourceArray returned;
251 TransferableResource::ReturnResources(reffed, &returned);
253 SetFrameProvider(frame.Pass());
255 scoped_refptr<DelegatedRendererLayer> observer1 =
256 DelegatedRendererLayer::Create(frame_provider_);
257 scoped_refptr<DelegatedRendererLayer> observer2 =
258 DelegatedRendererLayer::Create(frame_provider_);
260 gfx::RectF damage;
262 // Take a ref on each observer.
263 frame_provider_->GetFrameDataAndRefResources(observer1.get(), &damage);
264 frame_provider_->GetFrameDataAndRefResources(observer2.get(), &damage);
266 EXPECT_FALSE(ReturnAndResetResourcesAvailable());
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());
274 // Releasing all references to the frame provider will release
275 // the frame.
276 observer1 = nullptr;
277 observer2 = nullptr;
278 EXPECT_FALSE(ReturnAndResetResourcesAvailable());
280 frame_provider_ = nullptr;
282 EXPECT_TRUE(ReturnAndResetResourcesAvailable());
283 EXPECT_EQ(1u, resources_.size());
284 EXPECT_EQ(444u, resources_[0].id);
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);
293 TransferableResourceArray reffed = frame->resource_list;
294 ReturnedResourceArray returned;
295 TransferableResource::ReturnResources(reffed, &returned);
297 SetFrameProvider(frame.Pass());
299 scoped_refptr<DelegatedRendererLayer> observer1 =
300 DelegatedRendererLayer::Create(frame_provider_);
301 scoped_refptr<DelegatedRendererLayer> observer2 =
302 DelegatedRendererLayer::Create(frame_provider_);
304 gfx::RectF damage;
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());
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());
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());
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());
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());
336 TEST_F(DelegatedFrameProviderTest, LostNothing) {
337 scoped_ptr<DelegatedFrameData> frame =
338 CreateFrameData(gfx::Rect(5, 5), gfx::Rect(5, 5));
340 TransferableResourceArray reffed = frame->resource_list;
342 SetFrameProvider(frame.Pass());
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());
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);
357 SetFrameProvider(frame.Pass());
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);
364 SetFrameProvider(frame.Pass());
366 // There is something to lose.
367 EXPECT_FALSE(ReturnAndResetResourcesAvailable());
368 EXPECT_TRUE(resource_collection_->LoseAllResources());
369 EXPECT_TRUE(ReturnAndResetResourcesAvailable());
371 EXPECT_EQ(1u, resources_.size());
372 EXPECT_EQ(444u, resources_[0].id);
373 EXPECT_EQ(2, resources_[0].count);
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());
383 EXPECT_FALSE(ReturnAndResetResourcesAvailable());
385 // Lose all the resources.
386 EXPECT_TRUE(resource_collection_->LoseAllResources());
387 EXPECT_TRUE(ReturnAndResetResourcesAvailable());
388 resources_.clear();
390 frame_provider_ = nullptr;
392 // Nothing is returned twice.
393 EXPECT_FALSE(ReturnAndResetResourcesAvailable());
394 EXPECT_EQ(0u, resources_.size());
397 } // namespace
398 } // namespace cc