1 // Copyright 2015 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/tiles/software_image_decode_cache.h"
6 
7 #include "cc/paint/draw_image.h"
8 #include "cc/paint/paint_image_builder.h"
9 #include "cc/test/fake_paint_image_generator.h"
10 #include "cc/test/skia_common.h"
11 #include "cc/test/test_tile_task_runner.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/skia/include/core/SkRefCnt.h"
14 
15 namespace cc {
16 namespace {
17 
DefaultColorSpace()18 gfx::ColorSpace DefaultColorSpace() {
19   return gfx::ColorSpace::CreateSRGB();
20 }
21 
22 size_t kLockedMemoryLimitBytes = 128 * 1024 * 1024;
23 class TestSoftwareImageDecodeCache : public SoftwareImageDecodeCache {
24  public:
TestSoftwareImageDecodeCache()25   TestSoftwareImageDecodeCache()
26       : SoftwareImageDecodeCache(kN32_SkColorType,
27                                  kLockedMemoryLimitBytes,
28                                  PaintImage::kDefaultGeneratorClientId) {}
29 };
30 
CreateMatrix(const SkSize & scale,bool is_decomposable)31 SkMatrix CreateMatrix(const SkSize& scale, bool is_decomposable) {
32   SkMatrix matrix;
33   matrix.setScale(scale.width(), scale.height());
34 
35   if (!is_decomposable) {
36     // Perspective is not decomposable, add it.
37     matrix[SkMatrix::kMPersp0] = 0.1f;
38   }
39 
40   return matrix;
41 }
42 
CreatePaintImage(int width,int height,gfx::ColorSpace color_space=DefaultColorSpace ())43 PaintImage CreatePaintImage(int width,
44                             int height,
45                             gfx::ColorSpace color_space = DefaultColorSpace()) {
46   return CreateDiscardablePaintImage(gfx::Size(width, height),
47                                      color_space.ToSkColorSpace());
48 }
49 
TEST(SoftwareImageDecodeCacheTest,ImageKeyNoneQuality)50 TEST(SoftwareImageDecodeCacheTest, ImageKeyNoneQuality) {
51   PaintImage paint_image = CreatePaintImage(100, 100);
52   bool is_decomposable = true;
53   DrawImage draw_image(
54       paint_image, false,
55       SkIRect::MakeWH(paint_image.width(), paint_image.height()),
56       kNone_SkFilterQuality,
57       CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
58       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
59 
60   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
61       draw_image, kN32_SkColorType);
62   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
63   EXPECT_TRUE(key.is_nearest_neighbor());
64   EXPECT_EQ(100, key.target_size().width());
65   EXPECT_EQ(100, key.target_size().height());
66   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
67   // Since the original decode will be used, the locked_bytes is that of the
68   // original image.
69   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
70 }
71 
TEST(SoftwareImageDecodeCacheTest,ImageKeyLowQualityIncreasedToMediumIfDownscale)72 TEST(SoftwareImageDecodeCacheTest,
73      ImageKeyLowQualityIncreasedToMediumIfDownscale) {
74   PaintImage paint_image = CreatePaintImage(100, 100);
75   bool is_decomposable = true;
76   DrawImage draw_image(
77       paint_image, false,
78       SkIRect::MakeWH(paint_image.width(), paint_image.height()),
79       kLow_SkFilterQuality,
80       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
81       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
82 
83   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
84       draw_image, kN32_SkColorType);
85   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
86   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
87   EXPECT_EQ(50, key.target_size().width());
88   EXPECT_EQ(50, key.target_size().height());
89   EXPECT_EQ(50u * 50u * 4u, key.locked_bytes());
90 }
91 
TEST(SoftwareImageDecodeCacheTest,ImageKeyMediumQualityDropsToLowIfMipLevel0)92 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropsToLowIfMipLevel0) {
93   PaintImage paint_image = CreatePaintImage(100, 100);
94   bool is_decomposable = true;
95   DrawImage draw_image(
96       paint_image, false,
97       SkIRect::MakeWH(paint_image.width(), paint_image.height()),
98       kMedium_SkFilterQuality,
99       CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
100       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
101 
102   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
103       draw_image, kN32_SkColorType);
104   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
105   EXPECT_FALSE(key.is_nearest_neighbor());
106   EXPECT_EQ(100, key.target_size().width());
107   EXPECT_EQ(100, key.target_size().height());
108   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
109   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
110 }
111 
TEST(SoftwareImageDecodeCacheTest,LowUnscalableFormatStaysLow)112 TEST(SoftwareImageDecodeCacheTest, LowUnscalableFormatStaysLow) {
113   PaintImage paint_image = CreatePaintImage(100, 100);
114   bool is_decomposable = true;
115   DrawImage draw_image(
116       paint_image, false,
117       SkIRect::MakeWH(paint_image.width(), paint_image.height()),
118       kLow_SkFilterQuality,
119       CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
120       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
121 
122   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
123       draw_image, kARGB_4444_SkColorType);
124   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
125   EXPECT_FALSE(key.is_nearest_neighbor());
126   EXPECT_EQ(100, key.target_size().width());
127   EXPECT_EQ(100, key.target_size().height());
128   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
129   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
130 }
131 
TEST(SoftwareImageDecodeCacheTest,HighUnscalableFormatBecomesLow)132 TEST(SoftwareImageDecodeCacheTest, HighUnscalableFormatBecomesLow) {
133   PaintImage paint_image = CreatePaintImage(100, 100);
134   bool is_decomposable = true;
135   DrawImage draw_image(
136       paint_image, false,
137       SkIRect::MakeWH(paint_image.width(), paint_image.height()),
138       kHigh_SkFilterQuality,
139       CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
140       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
141 
142   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
143       draw_image, kARGB_4444_SkColorType);
144   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
145   EXPECT_FALSE(key.is_nearest_neighbor());
146   EXPECT_EQ(100, key.target_size().width());
147   EXPECT_EQ(100, key.target_size().height());
148   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
149   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
150 }
151 
TEST(SoftwareImageDecodeCacheTest,ImageKeyLowQualityKeptLowIfUpscale)152 TEST(SoftwareImageDecodeCacheTest, ImageKeyLowQualityKeptLowIfUpscale) {
153   PaintImage paint_image = CreatePaintImage(100, 100);
154   bool is_decomposable = true;
155   DrawImage draw_image(
156       paint_image, false,
157       SkIRect::MakeWH(paint_image.width(), paint_image.height()),
158       kLow_SkFilterQuality,
159       CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
160       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
161 
162   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
163       draw_image, kN32_SkColorType);
164   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
165   EXPECT_FALSE(key.is_nearest_neighbor());
166   EXPECT_EQ(100, key.target_size().width());
167   EXPECT_EQ(100, key.target_size().height());
168   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
169   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
170 }
171 
TEST(SoftwareImageDecodeCacheTest,ImageKeyMediumQuality)172 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQuality) {
173   PaintImage paint_image = CreatePaintImage(100, 100);
174   bool is_decomposable = true;
175   SkFilterQuality quality = kMedium_SkFilterQuality;
176 
177   DrawImage draw_image(
178       paint_image, false,
179       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
180       CreateMatrix(SkSize::Make(0.5f, 0.4f), is_decomposable),
181       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
182 
183   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
184       draw_image, kN32_SkColorType);
185   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
186   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
187   EXPECT_EQ(50, key.target_size().width());
188   EXPECT_EQ(50, key.target_size().height());
189   EXPECT_EQ(50u * 50u * 4u, key.locked_bytes());
190 }
191 
TEST(SoftwareImageDecodeCacheTest,ImageKeyMediumQualityDropToLowIfEnlarging)192 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropToLowIfEnlarging) {
193   PaintImage paint_image = CreatePaintImage(100, 100);
194   bool is_decomposable = true;
195   SkFilterQuality quality = kMedium_SkFilterQuality;
196 
197   DrawImage draw_image(
198       paint_image, false,
199       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
200       CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
201       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
202 
203   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
204       draw_image, kN32_SkColorType);
205   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
206   EXPECT_FALSE(key.is_nearest_neighbor());
207   EXPECT_EQ(100, key.target_size().width());
208   EXPECT_EQ(100, key.target_size().height());
209   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
210   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
211 }
212 
TEST(SoftwareImageDecodeCacheTest,ImageKeyMediumQualityDropToLowIfIdentity)213 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropToLowIfIdentity) {
214   PaintImage paint_image = CreatePaintImage(100, 100);
215   bool is_decomposable = true;
216   SkFilterQuality quality = kMedium_SkFilterQuality;
217 
218   DrawImage draw_image(
219       paint_image, false,
220       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
221       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
222       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
223 
224   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
225       draw_image, kN32_SkColorType);
226   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
227   EXPECT_FALSE(key.is_nearest_neighbor());
228   EXPECT_EQ(100, key.target_size().width());
229   EXPECT_EQ(100, key.target_size().height());
230   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
231   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
232 }
233 
TEST(SoftwareImageDecodeCacheTest,ImageKeyMediumQualityDropToLowIfNearlyIdentity)234 TEST(SoftwareImageDecodeCacheTest,
235      ImageKeyMediumQualityDropToLowIfNearlyIdentity) {
236   PaintImage paint_image = CreatePaintImage(100, 100);
237   bool is_decomposable = true;
238   SkFilterQuality quality = kMedium_SkFilterQuality;
239 
240   DrawImage draw_image(
241       paint_image, false,
242       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
243       CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
244       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
245 
246   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
247       draw_image, kN32_SkColorType);
248   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
249   EXPECT_FALSE(key.is_nearest_neighbor());
250   EXPECT_EQ(100, key.target_size().width());
251   EXPECT_EQ(100, key.target_size().height());
252   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
253   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
254 }
255 
TEST(SoftwareImageDecodeCacheTest,ImageKeyMediumQualityDropToLowIfNearlyIdentity2)256 TEST(SoftwareImageDecodeCacheTest,
257      ImageKeyMediumQualityDropToLowIfNearlyIdentity2) {
258   PaintImage paint_image = CreatePaintImage(100, 100);
259   bool is_decomposable = true;
260   SkFilterQuality quality = kMedium_SkFilterQuality;
261 
262   DrawImage draw_image(
263       paint_image, false,
264       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
265       CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
266       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
267 
268   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
269       draw_image, kN32_SkColorType);
270   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
271   EXPECT_FALSE(key.is_nearest_neighbor());
272   EXPECT_EQ(100, key.target_size().width());
273   EXPECT_EQ(100, key.target_size().height());
274   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
275   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
276 }
277 
TEST(SoftwareImageDecodeCacheTest,ImageKeyMediumQualityDropToLowIfNotDecomposable)278 TEST(SoftwareImageDecodeCacheTest,
279      ImageKeyMediumQualityDropToLowIfNotDecomposable) {
280   PaintImage paint_image = CreatePaintImage(100, 100);
281   bool is_decomposable = false;
282   SkFilterQuality quality = kMedium_SkFilterQuality;
283 
284   DrawImage draw_image(
285       paint_image, false,
286       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
287       CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
288       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
289 
290   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
291       draw_image, kN32_SkColorType);
292   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
293 
294   EXPECT_FALSE(key.is_nearest_neighbor());
295   EXPECT_EQ(100, key.target_size().width());
296   EXPECT_EQ(100, key.target_size().height());
297   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
298   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
299 }
300 
TEST(SoftwareImageDecodeCacheTest,ImageKeyMediumQualityAt1_5Scale)301 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt1_5Scale) {
302   PaintImage paint_image = CreatePaintImage(500, 200);
303   bool is_decomposable = true;
304   SkFilterQuality quality = kMedium_SkFilterQuality;
305 
306   DrawImage draw_image(
307       paint_image, false,
308       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
309       CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
310       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
311 
312   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
313       draw_image, kN32_SkColorType);
314   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
315   EXPECT_FALSE(key.is_nearest_neighbor());
316   EXPECT_EQ(500, key.target_size().width());
317   EXPECT_EQ(200, key.target_size().height());
318   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
319   EXPECT_EQ(500u * 200u * 4u, key.locked_bytes());
320 }
321 
TEST(SoftwareImageDecodeCacheTest,ImageKeyMediumQualityAt1_0cale)322 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt1_0cale) {
323   PaintImage paint_image = CreatePaintImage(500, 200);
324   bool is_decomposable = true;
325   SkFilterQuality quality = kMedium_SkFilterQuality;
326 
327   DrawImage draw_image(
328       paint_image, false,
329       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
330       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
331       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
332 
333   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
334       draw_image, kN32_SkColorType);
335   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
336   EXPECT_FALSE(key.is_nearest_neighbor());
337   EXPECT_EQ(500, key.target_size().width());
338   EXPECT_EQ(200, key.target_size().height());
339   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
340   EXPECT_EQ(500u * 200u * 4u, key.locked_bytes());
341 }
342 
TEST(SoftwareImageDecodeCacheTest,ImageKeyLowQualityAt0_75Scale)343 TEST(SoftwareImageDecodeCacheTest, ImageKeyLowQualityAt0_75Scale) {
344   PaintImage paint_image = CreatePaintImage(500, 200);
345   bool is_decomposable = true;
346   SkFilterQuality quality = kMedium_SkFilterQuality;
347 
348   DrawImage draw_image(
349       paint_image, false,
350       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
351       CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
352       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
353 
354   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
355       draw_image, kN32_SkColorType);
356   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
357   EXPECT_FALSE(key.is_nearest_neighbor());
358   EXPECT_EQ(500, key.target_size().width());
359   EXPECT_EQ(200, key.target_size().height());
360   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
361   EXPECT_EQ(500u * 200u * 4u, key.locked_bytes());
362 }
363 
TEST(SoftwareImageDecodeCacheTest,ImageKeyMediumQualityAt0_5Scale)364 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_5Scale) {
365   PaintImage paint_image = CreatePaintImage(500, 200);
366   bool is_decomposable = true;
367   SkFilterQuality quality = kMedium_SkFilterQuality;
368 
369   DrawImage draw_image(
370       paint_image, false,
371       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
372       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
373       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
374 
375   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
376       draw_image, kN32_SkColorType);
377   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
378   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
379   EXPECT_EQ(250, key.target_size().width());
380   EXPECT_EQ(100, key.target_size().height());
381   EXPECT_EQ(250u * 100u * 4u, key.locked_bytes());
382 }
383 
TEST(SoftwareImageDecodeCacheTest,ImageKeyMediumQualityAt0_49Scale)384 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_49Scale) {
385   PaintImage paint_image = CreatePaintImage(500, 200);
386   bool is_decomposable = true;
387   SkFilterQuality quality = kMedium_SkFilterQuality;
388 
389   DrawImage draw_image(
390       paint_image, false,
391       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
392       CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
393       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
394 
395   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
396       draw_image, kN32_SkColorType);
397   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
398   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
399   EXPECT_EQ(250, key.target_size().width());
400   EXPECT_EQ(100, key.target_size().height());
401   EXPECT_EQ(250u * 100u * 4u, key.locked_bytes());
402 }
403 
TEST(SoftwareImageDecodeCacheTest,ImageKeyMediumQualityAt0_1Scale)404 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_1Scale) {
405   PaintImage paint_image = CreatePaintImage(500, 200);
406   bool is_decomposable = true;
407   SkFilterQuality quality = kMedium_SkFilterQuality;
408 
409   DrawImage draw_image(
410       paint_image, false,
411       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
412       CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
413       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
414 
415   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
416       draw_image, kN32_SkColorType);
417   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
418   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
419   EXPECT_EQ(63, key.target_size().width());
420   EXPECT_EQ(25, key.target_size().height());
421   EXPECT_EQ(63u * 25u * 4u, key.locked_bytes());
422 }
423 
TEST(SoftwareImageDecodeCacheTest,ImageKeyMediumQualityAt0_01Scale)424 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_01Scale) {
425   PaintImage paint_image = CreatePaintImage(500, 200);
426   bool is_decomposable = true;
427   SkFilterQuality quality = kMedium_SkFilterQuality;
428 
429   DrawImage draw_image(
430       paint_image, false,
431       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
432       CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
433       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
434 
435   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
436       draw_image, kN32_SkColorType);
437   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
438   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
439   EXPECT_EQ(8, key.target_size().width());
440   EXPECT_EQ(4, key.target_size().height());
441   EXPECT_EQ(8u * 4u * 4u, key.locked_bytes());
442 }
443 
TEST(SoftwareImageDecodeCacheTest,ImageKeyFullDowscalesDropsHighQualityToMedium)444 TEST(SoftwareImageDecodeCacheTest,
445      ImageKeyFullDowscalesDropsHighQualityToMedium) {
446   PaintImage paint_image = CreatePaintImage(100, 100);
447   bool is_decomposable = true;
448   SkFilterQuality quality = kHigh_SkFilterQuality;
449 
450   DrawImage draw_image(
451       paint_image, false,
452       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
453       CreateMatrix(SkSize::Make(0.5f, 0.2f), is_decomposable),
454       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
455 
456   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
457       draw_image, kN32_SkColorType);
458   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
459   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
460   EXPECT_EQ(50, key.target_size().width());
461   EXPECT_EQ(50, key.target_size().height());
462   EXPECT_EQ(50u * 50u * 4u, key.locked_bytes());
463 }
464 
TEST(SoftwareImageDecodeCacheTest,ImageKeyUpscaleIsLowQuality)465 TEST(SoftwareImageDecodeCacheTest, ImageKeyUpscaleIsLowQuality) {
466   PaintImage paint_image = CreatePaintImage(100, 100);
467   bool is_decomposable = true;
468   SkFilterQuality quality = kHigh_SkFilterQuality;
469 
470   DrawImage draw_image(
471       paint_image, false,
472       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
473       CreateMatrix(SkSize::Make(2.5f, 1.5f), is_decomposable),
474       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
475 
476   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
477       draw_image, kN32_SkColorType);
478   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
479   EXPECT_FALSE(key.is_nearest_neighbor());
480   EXPECT_EQ(100, key.target_size().width());
481   EXPECT_EQ(100, key.target_size().height());
482   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
483   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
484 }
485 
TEST(SoftwareImageDecodeCacheTest,ImageKeyHighQualityDropToMediumIfTooLarge)486 TEST(SoftwareImageDecodeCacheTest, ImageKeyHighQualityDropToMediumIfTooLarge) {
487   // Just over 64MB when scaled.
488   PaintImage paint_image = CreatePaintImage(4555, 2048);
489   bool is_decomposable = true;
490   SkFilterQuality quality = kHigh_SkFilterQuality;
491 
492   // At least one dimension should scale down, so that medium quality doesn't
493   // become low.
494   DrawImage draw_image(
495       paint_image, false,
496       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
497       CreateMatrix(SkSize::Make(0.45f, 0.45f), is_decomposable),
498       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
499 
500   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
501       draw_image, kN32_SkColorType);
502   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
503   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
504   EXPECT_EQ(2278, key.target_size().width());
505   EXPECT_EQ(1024, key.target_size().height());
506   EXPECT_EQ(2278u * 1024u * 4u, key.locked_bytes());
507 }
508 
TEST(SoftwareImageDecodeCacheTest,ImageKeyHighQualityDropToLowIfNotDecomposable)509 TEST(SoftwareImageDecodeCacheTest,
510      ImageKeyHighQualityDropToLowIfNotDecomposable) {
511   PaintImage paint_image = CreatePaintImage(100, 100);
512   bool is_decomposable = false;
513   SkFilterQuality quality = kHigh_SkFilterQuality;
514 
515   DrawImage draw_image(
516       paint_image, false,
517       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
518       CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
519       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
520 
521   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
522       draw_image, kN32_SkColorType);
523   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
524   EXPECT_FALSE(key.is_nearest_neighbor());
525   EXPECT_EQ(100, key.target_size().width());
526   EXPECT_EQ(100, key.target_size().height());
527   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
528   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
529 }
530 
TEST(SoftwareImageDecodeCacheTest,ImageKeyHighQualityDropToLowIfIdentity)531 TEST(SoftwareImageDecodeCacheTest, ImageKeyHighQualityDropToLowIfIdentity) {
532   PaintImage paint_image = CreatePaintImage(100, 100);
533   bool is_decomposable = true;
534   SkFilterQuality quality = kHigh_SkFilterQuality;
535 
536   DrawImage draw_image(
537       paint_image, false,
538       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
539       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
540       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
541 
542   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
543       draw_image, kN32_SkColorType);
544   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
545   EXPECT_FALSE(key.is_nearest_neighbor());
546   EXPECT_EQ(100, key.target_size().width());
547   EXPECT_EQ(100, key.target_size().height());
548   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
549   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
550 }
551 
TEST(SoftwareImageDecodeCacheTest,ImageKeyHighQualityDropToLowIfNearlyIdentity)552 TEST(SoftwareImageDecodeCacheTest,
553      ImageKeyHighQualityDropToLowIfNearlyIdentity) {
554   PaintImage paint_image = CreatePaintImage(100, 100);
555   bool is_decomposable = true;
556   SkFilterQuality quality = kHigh_SkFilterQuality;
557 
558   DrawImage draw_image(
559       paint_image, false,
560       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
561       CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
562       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
563 
564   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
565       draw_image, kN32_SkColorType);
566   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
567   EXPECT_FALSE(key.is_nearest_neighbor());
568   EXPECT_EQ(100, key.target_size().width());
569   EXPECT_EQ(100, key.target_size().height());
570   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
571   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
572 }
573 
TEST(SoftwareImageDecodeCacheTest,ImageKeyHighQualityDropToLowIfNearlyIdentity2)574 TEST(SoftwareImageDecodeCacheTest,
575      ImageKeyHighQualityDropToLowIfNearlyIdentity2) {
576   PaintImage paint_image = CreatePaintImage(100, 100);
577   bool is_decomposable = true;
578   SkFilterQuality quality = kHigh_SkFilterQuality;
579 
580   DrawImage draw_image(
581       paint_image, false,
582       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
583       CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
584       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
585 
586   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
587       draw_image, kN32_SkColorType);
588   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
589   EXPECT_FALSE(key.is_nearest_neighbor());
590   EXPECT_EQ(100, key.target_size().width());
591   EXPECT_EQ(100, key.target_size().height());
592   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
593   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
594 }
595 
TEST(SoftwareImageDecodeCacheTest,ImageKeyDownscaleMipLevelWithRounding)596 TEST(SoftwareImageDecodeCacheTest, ImageKeyDownscaleMipLevelWithRounding) {
597   // Tests that, when using a non-zero mip level, the final target size (which
598   // is the size of the chosen mip level) is as expected if rounding is
599   // required.
600   //
601   // The 97x61 dimensions and the (0.2f, 0.2f) scaling were chosen specifically
602   // so that:
603   //
604   // - The starting target size is 19x12 which means that 2 is the chosen mip
605   //   level.
606   //
607   // - Attempting to get the final target size by simply multiplying the
608   //   dimensions of the |src_rect| (97x61) times
609   //   MipMapUtil::GetScaleAdjustmentForLevel() yields 24x15 if we attempt to
610   //   store the result as integers. This is inconsistent with the rounding
611   //   behavior introduced in https://crrev.com/c/1107049 and was the cause of
612   //   https://crbug.com/891316.
613   PaintImage paint_image = CreatePaintImage(97, 61);
614   bool is_decomposable = true;
615   DrawImage draw_image(
616       paint_image, false,
617       SkIRect::MakeWH(paint_image.width(), paint_image.height()),
618       kMedium_SkFilterQuality,
619       CreateMatrix(SkSize::Make(0.2f, 0.2f), is_decomposable),
620       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
621 
622   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
623       draw_image, kN32_SkColorType);
624   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
625   EXPECT_FALSE(key.is_nearest_neighbor());
626   EXPECT_EQ(25, key.target_size().width());
627   EXPECT_EQ(16, key.target_size().height());
628   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
629   EXPECT_EQ(25u * 16u * 4u, key.locked_bytes());
630 }
631 
TEST(SoftwareImageDecodeCacheTest,OriginalDecodesAreEqual)632 TEST(SoftwareImageDecodeCacheTest, OriginalDecodesAreEqual) {
633   PaintImage paint_image = CreatePaintImage(100, 100);
634   bool is_decomposable = true;
635   SkFilterQuality quality = kNone_SkFilterQuality;
636 
637   DrawImage draw_image(
638       paint_image, false,
639       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
640       CreateMatrix(SkSize::Make(0.5f, 0.5), is_decomposable),
641       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
642 
643   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
644       draw_image, kN32_SkColorType);
645   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
646   EXPECT_TRUE(key.is_nearest_neighbor());
647   EXPECT_EQ(100, key.target_size().width());
648   EXPECT_EQ(100, key.target_size().height());
649   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
650   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
651 
652   DrawImage another_draw_image(
653       paint_image, false,
654       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
655       CreateMatrix(SkSize::Make(1.5f, 1.5), is_decomposable),
656       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
657 
658   auto another_key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
659       another_draw_image, kN32_SkColorType);
660   EXPECT_EQ(another_draw_image.frame_key(), another_key.frame_key());
661   EXPECT_TRUE(another_key.is_nearest_neighbor());
662   EXPECT_EQ(100, another_key.target_size().width());
663   EXPECT_EQ(100, another_key.target_size().height());
664   EXPECT_EQ(another_key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
665   EXPECT_EQ(100u * 100u * 4u, another_key.locked_bytes());
666 
667   EXPECT_TRUE(key == another_key);
668 }
669 
TEST(SoftwareImageDecodeCacheTest,ImageRectDoesNotContainSrcRect)670 TEST(SoftwareImageDecodeCacheTest, ImageRectDoesNotContainSrcRect) {
671   PaintImage paint_image = CreatePaintImage(100, 100);
672   bool is_decomposable = true;
673   SkFilterQuality quality = kHigh_SkFilterQuality;
674 
675   DrawImage draw_image(
676       paint_image, false,
677       SkIRect::MakeXYWH(25, 35, paint_image.width(), paint_image.height()),
678       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
679       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
680 
681   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
682       draw_image, kN32_SkColorType);
683   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
684   EXPECT_FALSE(key.is_nearest_neighbor());
685   EXPECT_EQ(100, key.target_size().width());
686   EXPECT_EQ(100, key.target_size().height());
687   EXPECT_EQ(gfx::Rect(25, 35, 75, 65), key.src_rect());
688   EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
689 }
690 
TEST(SoftwareImageDecodeCacheTest,ImageRectDoesNotContainSrcRectWithScale)691 TEST(SoftwareImageDecodeCacheTest, ImageRectDoesNotContainSrcRectWithScale) {
692   PaintImage paint_image = CreatePaintImage(100, 100);
693   bool is_decomposable = true;
694   SkFilterQuality quality = kHigh_SkFilterQuality;
695 
696   DrawImage draw_image(
697       paint_image, false,
698       SkIRect::MakeXYWH(20, 30, paint_image.width(), paint_image.height()),
699       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
700       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
701 
702   auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
703       draw_image, kN32_SkColorType);
704   EXPECT_EQ(draw_image.frame_key(), key.frame_key());
705   EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
706   EXPECT_EQ(40, key.target_size().width());
707   EXPECT_EQ(35, key.target_size().height());
708   EXPECT_EQ(gfx::Rect(20, 30, 80, 70), key.src_rect());
709   EXPECT_EQ(40u * 35u * 4u, key.locked_bytes());
710 }
711 
TEST(SoftwareImageDecodeCacheTest,GetTaskForImageSameImage)712 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImage) {
713   TestSoftwareImageDecodeCache cache;
714   PaintImage paint_image = CreatePaintImage(100, 100);
715   bool is_decomposable = true;
716   SkFilterQuality quality = kHigh_SkFilterQuality;
717 
718   DrawImage draw_image(
719       paint_image, false,
720       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
721       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
722       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
723   ImageDecodeCache::TaskResult result =
724       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
725   EXPECT_TRUE(result.need_unref);
726   EXPECT_TRUE(result.task);
727 
728   DrawImage another_draw_image(
729       paint_image, false,
730       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
731       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
732       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
733   ImageDecodeCache::TaskResult another_result = cache.GetTaskForImageAndRef(
734       another_draw_image, ImageDecodeCache::TracingInfo());
735   EXPECT_TRUE(another_result.need_unref);
736   EXPECT_TRUE(result.task.get() == another_result.task.get());
737 
738   TestTileTaskRunner::ProcessTask(result.task.get());
739 
740   cache.UnrefImage(draw_image);
741   cache.UnrefImage(draw_image);
742 }
743 
TEST(SoftwareImageDecodeCacheTest,GetTaskForImageProcessUnrefCancel)744 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageProcessUnrefCancel) {
745   TestSoftwareImageDecodeCache cache;
746   PaintImage paint_image = CreatePaintImage(100, 100);
747   bool is_decomposable = true;
748   SkFilterQuality quality = kHigh_SkFilterQuality;
749 
750   DrawImage draw_image(
751       paint_image, false,
752       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
753       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
754       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
755   ImageDecodeCache::TaskResult result =
756       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
757   EXPECT_TRUE(result.need_unref);
758   EXPECT_TRUE(result.task);
759 
760   TestTileTaskRunner::ProcessTask(result.task.get());
761   cache.UnrefImage(draw_image);
762 
763   result =
764       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
765   EXPECT_TRUE(result.need_unref);
766   EXPECT_TRUE(result.task);
767 
768   TestTileTaskRunner::CancelTask(result.task.get());
769   TestTileTaskRunner::CompleteTask(result.task.get());
770   // This is expected to pass instead of DCHECKing since we're reducing the ref
771   // for an image which isn't locked to begin with.
772   cache.UnrefImage(draw_image);
773 }
774 
TEST(SoftwareImageDecodeCacheTest,GetTaskForImageSameImageDifferentQuality)775 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentQuality) {
776   TestSoftwareImageDecodeCache cache;
777   PaintImage paint_image = CreatePaintImage(100, 100);
778   bool is_decomposable = true;
779 
780   DrawImage high_quality_draw_image(
781       paint_image, false,
782       SkIRect::MakeWH(paint_image.width(), paint_image.height()),
783       kHigh_SkFilterQuality,
784       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
785       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
786   ImageDecodeCache::TaskResult high_quality_result =
787       cache.GetTaskForImageAndRef(high_quality_draw_image,
788                                   ImageDecodeCache::TracingInfo());
789   EXPECT_TRUE(high_quality_result.need_unref);
790   EXPECT_TRUE(high_quality_result.task);
791 
792   DrawImage none_quality_draw_image(
793       paint_image, false,
794       SkIRect::MakeWH(paint_image.width(), paint_image.height()),
795       kNone_SkFilterQuality,
796       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
797       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
798   ImageDecodeCache::TaskResult none_quality_result =
799       cache.GetTaskForImageAndRef(none_quality_draw_image,
800                                   ImageDecodeCache::TracingInfo());
801   EXPECT_TRUE(none_quality_result.need_unref);
802   EXPECT_TRUE(none_quality_result.task);
803   EXPECT_TRUE(high_quality_result.task.get() != none_quality_result.task.get());
804 
805   TestTileTaskRunner::ProcessTask(high_quality_result.task.get());
806   TestTileTaskRunner::ProcessTask(none_quality_result.task.get());
807 
808   cache.UnrefImage(high_quality_draw_image);
809   cache.UnrefImage(none_quality_draw_image);
810 }
811 
TEST(SoftwareImageDecodeCacheTest,GetTaskForImageSameImageDifferentSize)812 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentSize) {
813   TestSoftwareImageDecodeCache cache;
814   PaintImage paint_image = CreatePaintImage(100, 100);
815   bool is_decomposable = true;
816   SkFilterQuality quality = kHigh_SkFilterQuality;
817 
818   DrawImage half_size_draw_image(
819       paint_image, false,
820       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
821       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
822       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
823   ImageDecodeCache::TaskResult half_size_result = cache.GetTaskForImageAndRef(
824       half_size_draw_image, ImageDecodeCache::TracingInfo());
825   EXPECT_TRUE(half_size_result.need_unref);
826   EXPECT_TRUE(half_size_result.task);
827 
828   DrawImage quarter_size_draw_image(
829       paint_image, false,
830       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
831       CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
832       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
833   ImageDecodeCache::TaskResult quarter_size_result =
834       cache.GetTaskForImageAndRef(quarter_size_draw_image,
835                                   ImageDecodeCache::TracingInfo());
836   EXPECT_TRUE(quarter_size_result.need_unref);
837   EXPECT_TRUE(quarter_size_result.task);
838   EXPECT_TRUE(half_size_result.task.get() != quarter_size_result.task.get());
839 
840   TestTileTaskRunner::ProcessTask(half_size_result.task.get());
841   TestTileTaskRunner::ProcessTask(quarter_size_result.task.get());
842 
843   cache.UnrefImage(half_size_draw_image);
844   cache.UnrefImage(quarter_size_draw_image);
845 }
846 
TEST(SoftwareImageDecodeCacheTest,GetTaskForImageDifferentImage)847 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentImage) {
848   TestSoftwareImageDecodeCache cache;
849   bool is_decomposable = true;
850   SkFilterQuality quality = kHigh_SkFilterQuality;
851 
852   PaintImage first_paint_image = CreatePaintImage(100, 100);
853   DrawImage first_draw_image(
854       first_paint_image, false,
855       SkIRect::MakeWH(first_paint_image.width(), first_paint_image.height()),
856       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
857       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
858   ImageDecodeCache::TaskResult first_result = cache.GetTaskForImageAndRef(
859       first_draw_image, ImageDecodeCache::TracingInfo());
860   EXPECT_TRUE(first_result.need_unref);
861   EXPECT_TRUE(first_result.task);
862 
863   PaintImage second_paint_image = CreatePaintImage(100, 100);
864   DrawImage second_draw_image(
865       second_paint_image, false,
866       SkIRect::MakeWH(second_paint_image.width(), second_paint_image.height()),
867       quality, CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
868       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
869   ImageDecodeCache::TaskResult second_result = cache.GetTaskForImageAndRef(
870       second_draw_image, ImageDecodeCache::TracingInfo());
871   EXPECT_TRUE(second_result.need_unref);
872   EXPECT_TRUE(second_result.task);
873   EXPECT_TRUE(first_result.task.get() != second_result.task.get());
874 
875   TestTileTaskRunner::ProcessTask(first_result.task.get());
876   TestTileTaskRunner::ProcessTask(second_result.task.get());
877 
878   cache.UnrefImage(first_draw_image);
879   cache.UnrefImage(second_draw_image);
880 }
881 
882 // crbug.com/709341
883 #if defined(MEMORY_SANITIZER)
884 #define MAYBE_GetTaskForImageDifferentColorSpace \
885   DISABLED_GetTaskForImageDifferentColorSpace
886 #else
887 #define MAYBE_GetTaskForImageDifferentColorSpace \
888   GetTaskForImageDifferentColorSpace
889 #endif
TEST(SoftwareImageDecodeCacheTest,MAYBE_GetTaskForImageDifferentColorSpace)890 TEST(SoftwareImageDecodeCacheTest, MAYBE_GetTaskForImageDifferentColorSpace) {
891   TestSoftwareImageDecodeCache cache;
892   bool is_decomposable = true;
893   SkFilterQuality quality = kHigh_SkFilterQuality;
894 
895   gfx::ColorSpace color_space_a(gfx::ColorSpace::PrimaryID::XYZ_D50,
896                                 gfx::ColorSpace::TransferID::IEC61966_2_1);
897   gfx::ColorSpace color_space_b(gfx::ColorSpace::PrimaryID::SMPTE170M,
898                                 gfx::ColorSpace::TransferID::IEC61966_2_1);
899   gfx::ColorSpace color_space_c = gfx::ColorSpace::CreateSRGB();
900 
901   PaintImage paint_image = CreatePaintImage(100, 100, color_space_a);
902   DrawImage first_draw_image(
903       paint_image, false,
904       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
905       CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
906       PaintImage::kDefaultFrameIndex, color_space_b);
907   ImageDecodeCache::TaskResult first_result = cache.GetTaskForImageAndRef(
908       first_draw_image, ImageDecodeCache::TracingInfo());
909   EXPECT_TRUE(first_result.need_unref);
910   EXPECT_TRUE(first_result.task);
911 
912   DrawImage second_draw_image(
913       paint_image, false,
914       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
915       CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
916       PaintImage::kDefaultFrameIndex, color_space_c);
917   ImageDecodeCache::TaskResult second_result = cache.GetTaskForImageAndRef(
918       second_draw_image, ImageDecodeCache::TracingInfo());
919   EXPECT_TRUE(second_result.need_unref);
920   EXPECT_TRUE(second_result.task);
921   EXPECT_TRUE(first_result.task.get() != second_result.task.get());
922 
923   DrawImage third_draw_image(
924       paint_image, false,
925       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
926       CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
927       PaintImage::kDefaultFrameIndex, color_space_b);
928   ImageDecodeCache::TaskResult third_result = cache.GetTaskForImageAndRef(
929       third_draw_image, ImageDecodeCache::TracingInfo());
930   EXPECT_TRUE(third_result.need_unref);
931   EXPECT_TRUE(third_result.task);
932   EXPECT_TRUE(first_result.task.get() == third_result.task.get());
933 
934   TestTileTaskRunner::ProcessTask(first_result.task.get());
935   TestTileTaskRunner::ProcessTask(second_result.task.get());
936 
937   cache.UnrefImage(first_draw_image);
938   cache.UnrefImage(second_draw_image);
939   cache.UnrefImage(third_draw_image);
940 }
941 
TEST(SoftwareImageDecodeCacheTest,GetTaskForImageAlreadyDecoded)942 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyDecoded) {
943   TestSoftwareImageDecodeCache cache;
944   bool is_decomposable = true;
945   SkFilterQuality quality = kHigh_SkFilterQuality;
946 
947   PaintImage paint_image = CreatePaintImage(100, 100);
948   DrawImage draw_image(
949       paint_image, false,
950       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
951       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
952       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
953   ImageDecodeCache::TaskResult result =
954       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
955   EXPECT_TRUE(result.need_unref);
956   EXPECT_TRUE(result.task);
957 
958   TestTileTaskRunner::ScheduleTask(result.task.get());
959   TestTileTaskRunner::RunTask(result.task.get());
960 
961   ImageDecodeCache::TaskResult another_result =
962       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
963   EXPECT_TRUE(another_result.need_unref);
964   EXPECT_FALSE(another_result.task);
965 
966   TestTileTaskRunner::CompleteTask(result.task.get());
967 
968   cache.UnrefImage(draw_image);
969   cache.UnrefImage(draw_image);
970 }
971 
TEST(SoftwareImageDecodeCacheTest,GetTaskForImageAlreadyPrerolled)972 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyPrerolled) {
973   TestSoftwareImageDecodeCache cache;
974   bool is_decomposable = true;
975   SkFilterQuality quality = kLow_SkFilterQuality;
976 
977   PaintImage paint_image = CreatePaintImage(100, 100);
978   DrawImage draw_image(
979       paint_image, false,
980       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
981       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
982       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
983   ImageDecodeCache::TaskResult result =
984       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
985   EXPECT_TRUE(result.need_unref);
986   EXPECT_TRUE(result.task);
987 
988   TestTileTaskRunner::ScheduleTask(result.task.get());
989   TestTileTaskRunner::RunTask(result.task.get());
990 
991   ImageDecodeCache::TaskResult another_result =
992       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
993   EXPECT_TRUE(another_result.need_unref);
994   EXPECT_FALSE(another_result.task);
995 
996   TestTileTaskRunner::CompleteTask(result.task.get());
997 
998   ImageDecodeCache::TaskResult third_result =
999       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1000   EXPECT_TRUE(third_result.need_unref);
1001   EXPECT_FALSE(third_result.task);
1002 
1003   cache.UnrefImage(draw_image);
1004   cache.UnrefImage(draw_image);
1005   cache.UnrefImage(draw_image);
1006 }
1007 
TEST(SoftwareImageDecodeCacheTest,GetTaskForImageCanceledGetsNewTask)1008 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageCanceledGetsNewTask) {
1009   TestSoftwareImageDecodeCache cache;
1010   bool is_decomposable = true;
1011   SkFilterQuality quality = kHigh_SkFilterQuality;
1012 
1013   PaintImage paint_image = CreatePaintImage(100, 100);
1014   DrawImage draw_image(
1015       paint_image, false,
1016       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1017       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1018       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1019   ImageDecodeCache::TaskResult result =
1020       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1021   EXPECT_TRUE(result.need_unref);
1022   EXPECT_TRUE(result.task);
1023 
1024   ImageDecodeCache::TaskResult another_result =
1025       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1026   EXPECT_TRUE(another_result.need_unref);
1027   EXPECT_TRUE(another_result.task.get() == result.task.get());
1028 
1029   // Didn't run the task, complete it (it was canceled).
1030   TestTileTaskRunner::CancelTask(result.task.get());
1031   TestTileTaskRunner::CompleteTask(result.task.get());
1032 
1033   // Fully cancel everything (so the raster would unref things).
1034   cache.UnrefImage(draw_image);
1035   cache.UnrefImage(draw_image);
1036 
1037   // Here a new task is created.
1038   ImageDecodeCache::TaskResult third_result =
1039       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1040   EXPECT_TRUE(third_result.need_unref);
1041   EXPECT_TRUE(third_result.task);
1042   EXPECT_FALSE(third_result.task.get() == result.task.get());
1043 
1044   TestTileTaskRunner::ProcessTask(third_result.task.get());
1045 
1046   cache.UnrefImage(draw_image);
1047 }
1048 
TEST(SoftwareImageDecodeCacheTest,GetTaskForImageCanceledWhileReffedGetsNewTask)1049 TEST(SoftwareImageDecodeCacheTest,
1050      GetTaskForImageCanceledWhileReffedGetsNewTask) {
1051   TestSoftwareImageDecodeCache cache;
1052   bool is_decomposable = true;
1053   SkFilterQuality quality = kHigh_SkFilterQuality;
1054 
1055   PaintImage paint_image = CreatePaintImage(100, 100);
1056   DrawImage draw_image(
1057       paint_image, false,
1058       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1059       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1060       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1061   ImageDecodeCache::TaskResult result =
1062       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1063   EXPECT_TRUE(result.need_unref);
1064   EXPECT_TRUE(result.task);
1065 
1066   ImageDecodeCache::TaskResult another_result =
1067       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1068   EXPECT_TRUE(another_result.need_unref);
1069   EXPECT_TRUE(another_result.task.get() == result.task.get());
1070 
1071   // Didn't run the task, complete it (it was canceled).
1072   TestTileTaskRunner::CancelTask(result.task.get());
1073   TestTileTaskRunner::CompleteTask(result.task.get());
1074 
1075   // Note that here, everything is reffed, but a new task is created. This is
1076   // possible with repeated schedule/cancel operations.
1077   ImageDecodeCache::TaskResult third_result =
1078       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1079   EXPECT_TRUE(third_result.need_unref);
1080   EXPECT_TRUE(third_result.task);
1081   EXPECT_FALSE(third_result.task.get() == result.task.get());
1082 
1083   TestTileTaskRunner::ProcessTask(third_result.task.get());
1084 
1085   // 3 Unrefs!!!
1086   cache.UnrefImage(draw_image);
1087   cache.UnrefImage(draw_image);
1088   cache.UnrefImage(draw_image);
1089 }
1090 
TEST(SoftwareImageDecodeCacheTest,GetDecodedImageForDraw)1091 TEST(SoftwareImageDecodeCacheTest, GetDecodedImageForDraw) {
1092   TestSoftwareImageDecodeCache cache;
1093   bool is_decomposable = true;
1094   SkFilterQuality quality = kHigh_SkFilterQuality;
1095 
1096   PaintImage paint_image = CreatePaintImage(100, 100);
1097   DrawImage draw_image(
1098       paint_image, false,
1099       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1100       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1101       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1102   ImageDecodeCache::TaskResult result =
1103       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1104   EXPECT_TRUE(result.need_unref);
1105   EXPECT_TRUE(result.task);
1106 
1107   TestTileTaskRunner::ProcessTask(result.task.get());
1108 
1109   DecodedDrawImage decoded_draw_image =
1110       cache.GetDecodedImageForDraw(draw_image);
1111   EXPECT_TRUE(decoded_draw_image.image());
1112   EXPECT_EQ(50, decoded_draw_image.image()->width());
1113   EXPECT_EQ(50, decoded_draw_image.image()->height());
1114   EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
1115   EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
1116   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
1117   EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
1118 
1119   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1120   cache.UnrefImage(draw_image);
1121 }
1122 
TEST(SoftwareImageDecodeCacheTest,GetDecodedImageForDrawWithNonContainedSrcRect)1123 TEST(SoftwareImageDecodeCacheTest,
1124      GetDecodedImageForDrawWithNonContainedSrcRect) {
1125   TestSoftwareImageDecodeCache cache;
1126   bool is_decomposable = true;
1127   SkFilterQuality quality = kHigh_SkFilterQuality;
1128 
1129   PaintImage paint_image = CreatePaintImage(100, 100);
1130   DrawImage draw_image(
1131       paint_image, false,
1132       SkIRect::MakeXYWH(20, 30, paint_image.width(), paint_image.height()),
1133       quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1134       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1135   ImageDecodeCache::TaskResult result =
1136       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1137   EXPECT_TRUE(result.need_unref);
1138   EXPECT_TRUE(result.task);
1139 
1140   TestTileTaskRunner::ProcessTask(result.task.get());
1141 
1142   DecodedDrawImage decoded_draw_image =
1143       cache.GetDecodedImageForDraw(draw_image);
1144   EXPECT_TRUE(decoded_draw_image.image());
1145   EXPECT_EQ(40, decoded_draw_image.image()->width());
1146   EXPECT_EQ(35, decoded_draw_image.image()->height());
1147   EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
1148   EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
1149   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
1150   EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
1151 
1152   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1153   cache.UnrefImage(draw_image);
1154 }
1155 
TEST(SoftwareImageDecodeCacheTest,GetDecodedImageForDrawAtRasterDecode)1156 TEST(SoftwareImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) {
1157   TestSoftwareImageDecodeCache cache;
1158   bool is_decomposable = true;
1159   SkFilterQuality quality = kHigh_SkFilterQuality;
1160 
1161   PaintImage paint_image = CreatePaintImage(100, 100);
1162   DrawImage draw_image(
1163       paint_image, false,
1164       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1165       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1166       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1167 
1168   DecodedDrawImage decoded_draw_image =
1169       cache.GetDecodedImageForDraw(draw_image);
1170   EXPECT_TRUE(decoded_draw_image.image());
1171   EXPECT_EQ(50, decoded_draw_image.image()->width());
1172   EXPECT_EQ(50, decoded_draw_image.image()->height());
1173   EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
1174   EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
1175   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
1176   EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
1177 
1178   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1179 }
1180 
TEST(SoftwareImageDecodeCacheTest,GetDecodedImageForDrawAtRasterDecodeMultipleTimes)1181 TEST(SoftwareImageDecodeCacheTest,
1182      GetDecodedImageForDrawAtRasterDecodeMultipleTimes) {
1183   TestSoftwareImageDecodeCache cache;
1184   bool is_decomposable = true;
1185   SkFilterQuality quality = kHigh_SkFilterQuality;
1186 
1187   PaintImage paint_image = CreatePaintImage(100, 100);
1188   DrawImage draw_image(
1189       paint_image, false,
1190       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1191       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1192       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1193 
1194   DecodedDrawImage decoded_draw_image =
1195       cache.GetDecodedImageForDraw(draw_image);
1196   ASSERT_TRUE(decoded_draw_image.image());
1197   EXPECT_EQ(50, decoded_draw_image.image()->width());
1198   EXPECT_EQ(50, decoded_draw_image.image()->height());
1199   EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
1200   EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
1201   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
1202   EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
1203 
1204   DecodedDrawImage another_decoded_draw_image =
1205       cache.GetDecodedImageForDraw(draw_image);
1206   EXPECT_EQ(decoded_draw_image.image()->uniqueID(),
1207             another_decoded_draw_image.image()->uniqueID());
1208 
1209   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1210   cache.DrawWithImageFinished(draw_image, another_decoded_draw_image);
1211 }
1212 
TEST(SoftwareImageDecodeCacheTest,ZeroSizedImagesAreSkipped)1213 TEST(SoftwareImageDecodeCacheTest, ZeroSizedImagesAreSkipped) {
1214   TestSoftwareImageDecodeCache cache;
1215   bool is_decomposable = true;
1216   SkFilterQuality quality = kHigh_SkFilterQuality;
1217 
1218   PaintImage paint_image = CreatePaintImage(100, 100);
1219   DrawImage draw_image(
1220       paint_image, false,
1221       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1222       CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable),
1223       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1224 
1225   ImageDecodeCache::TaskResult result =
1226       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1227   EXPECT_FALSE(result.task);
1228   EXPECT_FALSE(result.need_unref);
1229 
1230   DecodedDrawImage decoded_draw_image =
1231       cache.GetDecodedImageForDraw(draw_image);
1232   EXPECT_FALSE(decoded_draw_image.image());
1233 
1234   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1235 }
1236 
TEST(SoftwareImageDecodeCacheTest,NonOverlappingSrcRectImagesAreSkipped)1237 TEST(SoftwareImageDecodeCacheTest, NonOverlappingSrcRectImagesAreSkipped) {
1238   TestSoftwareImageDecodeCache cache;
1239   bool is_decomposable = true;
1240   SkFilterQuality quality = kHigh_SkFilterQuality;
1241 
1242   PaintImage paint_image = CreatePaintImage(100, 100);
1243   DrawImage draw_image(
1244       paint_image, false,
1245       SkIRect::MakeXYWH(150, 150, paint_image.width(), paint_image.height()),
1246       quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1247       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1248 
1249   ImageDecodeCache::TaskResult result =
1250       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1251   EXPECT_FALSE(result.task);
1252   EXPECT_FALSE(result.need_unref);
1253 
1254   DecodedDrawImage decoded_draw_image =
1255       cache.GetDecodedImageForDraw(draw_image);
1256   EXPECT_FALSE(decoded_draw_image.image());
1257 
1258   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1259 }
1260 
TEST(SoftwareImageDecodeCacheTest,LowQualityFilterIsHandled)1261 TEST(SoftwareImageDecodeCacheTest, LowQualityFilterIsHandled) {
1262   TestSoftwareImageDecodeCache cache;
1263   bool is_decomposable = true;
1264   SkFilterQuality quality = kLow_SkFilterQuality;
1265 
1266   PaintImage paint_image = CreatePaintImage(100, 100);
1267   DrawImage draw_image(
1268       paint_image, false,
1269       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1270       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1271       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1272 
1273   ImageDecodeCache::TaskResult result =
1274       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1275   EXPECT_TRUE(result.task);
1276   EXPECT_TRUE(result.need_unref);
1277 
1278   TestTileTaskRunner::ProcessTask(result.task.get());
1279 
1280   DecodedDrawImage decoded_draw_image =
1281       cache.GetDecodedImageForDraw(draw_image);
1282   EXPECT_TRUE(decoded_draw_image.image());
1283   // If we decoded the image and cached it, it would be stored in a different
1284   // SkImage object.
1285   EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1286 
1287   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1288   cache.UnrefImage(draw_image);
1289 }
1290 
TEST(SoftwareImageDecodeCacheTest,LowQualityScaledSubrectIsHandled)1291 TEST(SoftwareImageDecodeCacheTest, LowQualityScaledSubrectIsHandled) {
1292   TestSoftwareImageDecodeCache cache;
1293   bool is_decomposable = true;
1294   SkFilterQuality quality = kLow_SkFilterQuality;
1295 
1296   PaintImage paint_image = CreatePaintImage(100, 100);
1297   DrawImage draw_image(paint_image, false, SkIRect::MakeXYWH(10, 10, 80, 80),
1298                        quality,
1299                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1300                        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1301 
1302   ImageDecodeCache::TaskResult result =
1303       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1304   EXPECT_TRUE(result.task);
1305   EXPECT_TRUE(result.need_unref);
1306 
1307   TestTileTaskRunner::ProcessTask(result.task.get());
1308 
1309   DecodedDrawImage decoded_draw_image =
1310       cache.GetDecodedImageForDraw(draw_image);
1311   EXPECT_TRUE(decoded_draw_image.image());
1312   // If we decoded the image and cached it, it would be stored in a different
1313   // SkImage object.
1314   EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1315   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
1316   // Low quality will be upgraded to medium and mip-mapped.
1317   EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
1318   EXPECT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
1319   EXPECT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
1320 
1321   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1322   cache.UnrefImage(draw_image);
1323 }
1324 
TEST(SoftwareImageDecodeCacheTest,NoneQualityScaledSubrectIsHandled)1325 TEST(SoftwareImageDecodeCacheTest, NoneQualityScaledSubrectIsHandled) {
1326   TestSoftwareImageDecodeCache cache;
1327   bool is_decomposable = true;
1328   SkFilterQuality quality = kNone_SkFilterQuality;
1329 
1330   PaintImage paint_image = CreatePaintImage(100, 100);
1331   DrawImage draw_image(paint_image, false, SkIRect::MakeXYWH(10, 10, 80, 80),
1332                        quality,
1333                        CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1334                        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1335 
1336   ImageDecodeCache::TaskResult result =
1337       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1338   EXPECT_TRUE(result.task);
1339   EXPECT_TRUE(result.need_unref);
1340 
1341   TestTileTaskRunner::ProcessTask(result.task.get());
1342 
1343   DecodedDrawImage decoded_draw_image =
1344       cache.GetDecodedImageForDraw(draw_image);
1345   EXPECT_TRUE(decoded_draw_image.image());
1346   // If we decoded the image and cached it, it would be stored in a different
1347   // SkImage object.
1348   EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1349   EXPECT_EQ(kNone_SkFilterQuality, decoded_draw_image.filter_quality());
1350   EXPECT_TRUE(decoded_draw_image.is_scale_adjustment_identity());
1351 
1352   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1353   cache.UnrefImage(draw_image);
1354 }
1355 
TEST(SoftwareImageDecodeCacheTest,MediumQualityAt01_5ScaleIsHandled)1356 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt01_5ScaleIsHandled) {
1357   TestSoftwareImageDecodeCache cache;
1358   bool is_decomposable = true;
1359   SkFilterQuality quality = kMedium_SkFilterQuality;
1360 
1361   PaintImage paint_image = CreatePaintImage(500, 200);
1362   DrawImage draw_image(
1363       paint_image, false,
1364       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1365       CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
1366       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1367 
1368   ImageDecodeCache::TaskResult result =
1369       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1370   EXPECT_TRUE(result.task);
1371   EXPECT_TRUE(result.need_unref);
1372 
1373   TestTileTaskRunner::ProcessTask(result.task.get());
1374 
1375   DecodedDrawImage decoded_draw_image =
1376       cache.GetDecodedImageForDraw(draw_image);
1377   EXPECT_TRUE(decoded_draw_image.image());
1378   // Decoded image should not be lazy generated.
1379   EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1380   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
1381   EXPECT_EQ(500, decoded_draw_image.image()->width());
1382   EXPECT_EQ(200, decoded_draw_image.image()->height());
1383 
1384   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1385   cache.UnrefImage(draw_image);
1386 }
1387 
TEST(SoftwareImageDecodeCacheTest,MediumQualityAt1_0ScaleIsHandled)1388 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt1_0ScaleIsHandled) {
1389   TestSoftwareImageDecodeCache cache;
1390   bool is_decomposable = true;
1391   SkFilterQuality quality = kMedium_SkFilterQuality;
1392 
1393   PaintImage paint_image = CreatePaintImage(500, 200);
1394   DrawImage draw_image(
1395       paint_image, false,
1396       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1397       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1398       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1399 
1400   ImageDecodeCache::TaskResult result =
1401       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1402   EXPECT_TRUE(result.task);
1403   EXPECT_TRUE(result.need_unref);
1404 
1405   TestTileTaskRunner::ProcessTask(result.task.get());
1406 
1407   DecodedDrawImage decoded_draw_image =
1408       cache.GetDecodedImageForDraw(draw_image);
1409   EXPECT_TRUE(decoded_draw_image.image());
1410   // Decoded image should not be lazy generated.
1411   EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1412   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
1413   EXPECT_EQ(500, decoded_draw_image.image()->width());
1414   EXPECT_EQ(200, decoded_draw_image.image()->height());
1415 
1416   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1417   cache.UnrefImage(draw_image);
1418 }
1419 
TEST(SoftwareImageDecodeCacheTest,MediumQualityAt0_75ScaleIsHandled)1420 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_75ScaleIsHandled) {
1421   TestSoftwareImageDecodeCache cache;
1422   bool is_decomposable = true;
1423   SkFilterQuality quality = kMedium_SkFilterQuality;
1424 
1425   PaintImage paint_image = CreatePaintImage(500, 200);
1426   DrawImage draw_image(
1427       paint_image, false,
1428       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1429       CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
1430       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1431 
1432   ImageDecodeCache::TaskResult result =
1433       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1434   EXPECT_TRUE(result.task);
1435   EXPECT_TRUE(result.need_unref);
1436 
1437   TestTileTaskRunner::ProcessTask(result.task.get());
1438 
1439   DecodedDrawImage decoded_draw_image =
1440       cache.GetDecodedImageForDraw(draw_image);
1441   EXPECT_TRUE(decoded_draw_image.image());
1442   // Decoded image should not be lazy generated.
1443   EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1444   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
1445   EXPECT_EQ(500, decoded_draw_image.image()->width());
1446   EXPECT_EQ(200, decoded_draw_image.image()->height());
1447 
1448   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1449   cache.UnrefImage(draw_image);
1450 }
1451 
TEST(SoftwareImageDecodeCacheTest,MediumQualityAt0_5ScaleIsHandled)1452 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_5ScaleIsHandled) {
1453   TestSoftwareImageDecodeCache cache;
1454   bool is_decomposable = true;
1455   SkFilterQuality quality = kMedium_SkFilterQuality;
1456 
1457   PaintImage paint_image = CreatePaintImage(500, 200);
1458   DrawImage draw_image(
1459       paint_image, false,
1460       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1461       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1462       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1463 
1464   ImageDecodeCache::TaskResult result =
1465       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1466   EXPECT_TRUE(result.task);
1467   EXPECT_TRUE(result.need_unref);
1468 
1469   TestTileTaskRunner::ProcessTask(result.task.get());
1470 
1471   DecodedDrawImage decoded_draw_image =
1472       cache.GetDecodedImageForDraw(draw_image);
1473   EXPECT_TRUE(decoded_draw_image.image());
1474   // Decoded image should not be lazy generated.
1475   EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1476   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
1477   EXPECT_EQ(250, decoded_draw_image.image()->width());
1478   EXPECT_EQ(100, decoded_draw_image.image()->height());
1479 
1480   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1481   cache.UnrefImage(draw_image);
1482 }
1483 
TEST(SoftwareImageDecodeCacheTest,MediumQualityAt0_49ScaleIsHandled)1484 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_49ScaleIsHandled) {
1485   TestSoftwareImageDecodeCache cache;
1486   bool is_decomposable = true;
1487   SkFilterQuality quality = kMedium_SkFilterQuality;
1488 
1489   PaintImage paint_image = CreatePaintImage(500, 200);
1490   DrawImage draw_image(
1491       paint_image, false,
1492       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1493       CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
1494       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1495 
1496   ImageDecodeCache::TaskResult result =
1497       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1498   EXPECT_TRUE(result.task);
1499   EXPECT_TRUE(result.need_unref);
1500 
1501   TestTileTaskRunner::ProcessTask(result.task.get());
1502 
1503   DecodedDrawImage decoded_draw_image =
1504       cache.GetDecodedImageForDraw(draw_image);
1505   EXPECT_TRUE(decoded_draw_image.image());
1506   // Decoded image should not be lazy generated.
1507   EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1508   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
1509   EXPECT_EQ(250, decoded_draw_image.image()->width());
1510   EXPECT_EQ(100, decoded_draw_image.image()->height());
1511 
1512   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1513   cache.UnrefImage(draw_image);
1514 }
1515 
TEST(SoftwareImageDecodeCacheTest,MediumQualityAt0_1ScaleIsHandled)1516 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_1ScaleIsHandled) {
1517   TestSoftwareImageDecodeCache cache;
1518   bool is_decomposable = true;
1519   SkFilterQuality quality = kMedium_SkFilterQuality;
1520 
1521   PaintImage paint_image = CreatePaintImage(500, 200);
1522   DrawImage draw_image(
1523       paint_image, false,
1524       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1525       CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
1526       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1527 
1528   ImageDecodeCache::TaskResult result =
1529       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1530   EXPECT_TRUE(result.task);
1531   EXPECT_TRUE(result.need_unref);
1532 
1533   TestTileTaskRunner::ProcessTask(result.task.get());
1534 
1535   DecodedDrawImage decoded_draw_image =
1536       cache.GetDecodedImageForDraw(draw_image);
1537   EXPECT_TRUE(decoded_draw_image.image());
1538   // Decoded image should not be lazy generated.
1539   EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1540   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
1541   EXPECT_EQ(63, decoded_draw_image.image()->width());
1542   EXPECT_EQ(25, decoded_draw_image.image()->height());
1543 
1544   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1545   cache.UnrefImage(draw_image);
1546 }
1547 
TEST(SoftwareImageDecodeCacheTest,MediumQualityAt0_01ScaleIsHandled)1548 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_01ScaleIsHandled) {
1549   TestSoftwareImageDecodeCache cache;
1550   bool is_decomposable = true;
1551   SkFilterQuality quality = kMedium_SkFilterQuality;
1552 
1553   PaintImage paint_image = CreatePaintImage(500, 200);
1554   DrawImage draw_image(
1555       paint_image, false,
1556       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1557       CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
1558       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1559 
1560   ImageDecodeCache::TaskResult result =
1561       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1562   EXPECT_TRUE(result.task);
1563   EXPECT_TRUE(result.need_unref);
1564 
1565   TestTileTaskRunner::ProcessTask(result.task.get());
1566 
1567   DecodedDrawImage decoded_draw_image =
1568       cache.GetDecodedImageForDraw(draw_image);
1569   EXPECT_TRUE(decoded_draw_image.image());
1570   // Decoded image should not be lazy generated.
1571   EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1572   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
1573   EXPECT_EQ(8, decoded_draw_image.image()->width());
1574   EXPECT_EQ(4, decoded_draw_image.image()->height());
1575 
1576   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1577   cache.UnrefImage(draw_image);
1578 }
1579 
TEST(SoftwareImageDecodeCacheTest,MediumQualityAt0_001ScaleIsHandled)1580 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_001ScaleIsHandled) {
1581   TestSoftwareImageDecodeCache cache;
1582   bool is_decomposable = true;
1583   SkFilterQuality quality = kMedium_SkFilterQuality;
1584 
1585   PaintImage paint_image = CreatePaintImage(500, 200);
1586   DrawImage draw_image(
1587       paint_image, false,
1588       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1589       CreateMatrix(SkSize::Make(0.001f, 0.001f), is_decomposable),
1590       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1591 
1592   ImageDecodeCache::TaskResult result =
1593       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1594   EXPECT_FALSE(result.task);
1595   EXPECT_FALSE(result.need_unref);
1596 
1597   DecodedDrawImage decoded_draw_image =
1598       cache.GetDecodedImageForDraw(draw_image);
1599   EXPECT_FALSE(decoded_draw_image.image());
1600 
1601   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1602 }
1603 
TEST(SoftwareImageDecodeCacheTest,MediumQualityImagesAreTheSameAt0_5And0_49Scale)1604 TEST(SoftwareImageDecodeCacheTest,
1605      MediumQualityImagesAreTheSameAt0_5And0_49Scale) {
1606   TestSoftwareImageDecodeCache cache;
1607   bool is_decomposable = true;
1608   SkFilterQuality quality = kMedium_SkFilterQuality;
1609 
1610   PaintImage paint_image = CreatePaintImage(500, 200);
1611   DrawImage draw_image_50(
1612       paint_image, false,
1613       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1614       CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1615       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1616   DrawImage draw_image_49(
1617       paint_image, false,
1618       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1619       CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
1620       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1621 
1622   ImageDecodeCache::TaskResult result_50 = cache.GetTaskForImageAndRef(
1623       draw_image_50, ImageDecodeCache::TracingInfo());
1624   EXPECT_TRUE(result_50.task);
1625   EXPECT_TRUE(result_50.need_unref);
1626   ImageDecodeCache::TaskResult result_49 = cache.GetTaskForImageAndRef(
1627       draw_image_49, ImageDecodeCache::TracingInfo());
1628   EXPECT_TRUE(result_49.task);
1629   EXPECT_TRUE(result_49.need_unref);
1630 
1631   TestTileTaskRunner::ProcessTask(result_49.task.get());
1632 
1633   DecodedDrawImage decoded_draw_image_50 =
1634       cache.GetDecodedImageForDraw(draw_image_50);
1635   EXPECT_TRUE(decoded_draw_image_50.image());
1636   DecodedDrawImage decoded_draw_image_49 =
1637       cache.GetDecodedImageForDraw(draw_image_49);
1638   EXPECT_TRUE(decoded_draw_image_49.image());
1639   // Decoded image should not be lazy generated.
1640   EXPECT_FALSE(decoded_draw_image_50.image()->isLazyGenerated());
1641   EXPECT_FALSE(decoded_draw_image_49.image()->isLazyGenerated());
1642   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image_50.filter_quality());
1643   EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image_49.filter_quality());
1644   EXPECT_EQ(250, decoded_draw_image_50.image()->width());
1645   EXPECT_EQ(250, decoded_draw_image_49.image()->width());
1646   EXPECT_EQ(100, decoded_draw_image_50.image()->height());
1647   EXPECT_EQ(100, decoded_draw_image_49.image()->height());
1648 
1649   EXPECT_EQ(decoded_draw_image_50.image(), decoded_draw_image_49.image());
1650 
1651   cache.DrawWithImageFinished(draw_image_50, decoded_draw_image_50);
1652   cache.UnrefImage(draw_image_50);
1653   cache.DrawWithImageFinished(draw_image_49, decoded_draw_image_49);
1654   cache.UnrefImage(draw_image_49);
1655 }
1656 
TEST(SoftwareImageDecodeCacheTest,ClearCache)1657 TEST(SoftwareImageDecodeCacheTest, ClearCache) {
1658   TestSoftwareImageDecodeCache cache;
1659   bool is_decomposable = true;
1660   SkFilterQuality quality = kHigh_SkFilterQuality;
1661 
1662   for (int i = 0; i < 10; ++i) {
1663     PaintImage paint_image = CreatePaintImage(100, 100);
1664     DrawImage draw_image(
1665         paint_image, false,
1666         SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1667         CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
1668         PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1669     ImageDecodeCache::TaskResult result = cache.GetTaskForImageAndRef(
1670         draw_image, ImageDecodeCache::TracingInfo());
1671     EXPECT_TRUE(result.need_unref);
1672     EXPECT_TRUE(result.task);
1673     TestTileTaskRunner::ProcessTask(result.task.get());
1674     cache.UnrefImage(draw_image);
1675   }
1676 
1677   EXPECT_EQ(10u, cache.GetNumCacheEntriesForTesting());
1678 
1679   // Tell our cache to clear resources.
1680   cache.ClearCache();
1681 
1682   EXPECT_EQ(0u, cache.GetNumCacheEntriesForTesting());
1683 }
1684 
TEST(SoftwareImageDecodeCacheTest,CacheDecodesExpectedFrames)1685 TEST(SoftwareImageDecodeCacheTest, CacheDecodesExpectedFrames) {
1686   TestSoftwareImageDecodeCache cache;
1687   std::vector<FrameMetadata> frames = {
1688       FrameMetadata(true, base::TimeDelta::FromMilliseconds(2)),
1689       FrameMetadata(true, base::TimeDelta::FromMilliseconds(3)),
1690       FrameMetadata(true, base::TimeDelta::FromMilliseconds(4)),
1691       FrameMetadata(true, base::TimeDelta::FromMilliseconds(5)),
1692   };
1693   sk_sp<FakePaintImageGenerator> generator =
1694       sk_make_sp<FakePaintImageGenerator>(
1695           SkImageInfo::MakeN32Premul(10, 10, SkColorSpace::MakeSRGB()), frames);
1696   PaintImage image = PaintImageBuilder::WithDefault()
1697                          .set_id(PaintImage::GetNextId())
1698                          .set_paint_image_generator(generator)
1699                          .TakePaintImage();
1700 
1701   bool is_decomposable = true;
1702   SkFilterQuality quality = kHigh_SkFilterQuality;
1703   DrawImage draw_image(image, false,
1704                        SkIRect::MakeWH(image.width(), image.height()), quality,
1705                        CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
1706                        1u, DefaultColorSpace());
1707   auto decoded_image = cache.GetDecodedImageForDraw(draw_image);
1708   ASSERT_TRUE(decoded_image.image());
1709   ASSERT_EQ(generator->frames_decoded().size(), 1u);
1710   EXPECT_EQ(generator->frames_decoded().count(1u), 1u);
1711   generator->reset_frames_decoded();
1712   cache.DrawWithImageFinished(draw_image, decoded_image);
1713 
1714   // Scaled.
1715   DrawImage scaled_draw_image(draw_image, 0.5f, 2u,
1716                               draw_image.target_color_space());
1717   decoded_image = cache.GetDecodedImageForDraw(scaled_draw_image);
1718   ASSERT_TRUE(decoded_image.image());
1719   ASSERT_EQ(generator->frames_decoded().size(), 1u);
1720   EXPECT_EQ(generator->frames_decoded().count(2u), 1u);
1721   generator->reset_frames_decoded();
1722   cache.DrawWithImageFinished(scaled_draw_image, decoded_image);
1723 
1724   // Subset.
1725   DrawImage subset_draw_image(
1726       image, false, SkIRect::MakeWH(5, 5), quality,
1727       CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), 3u,
1728       DefaultColorSpace());
1729   decoded_image = cache.GetDecodedImageForDraw(subset_draw_image);
1730   ASSERT_TRUE(decoded_image.image());
1731   ASSERT_EQ(generator->frames_decoded().size(), 1u);
1732   EXPECT_EQ(generator->frames_decoded().count(3u), 1u);
1733   generator->reset_frames_decoded();
1734   cache.DrawWithImageFinished(subset_draw_image, decoded_image);
1735 }
1736 
TEST(SoftwareImageDecodeCacheTest,SizeSubrectingIsHandled)1737 TEST(SoftwareImageDecodeCacheTest, SizeSubrectingIsHandled) {
1738   const int min_dimension = 4 * 1024 + 2;
1739   TestSoftwareImageDecodeCache cache;
1740   bool is_decomposable = true;
1741   SkFilterQuality quality = kLow_SkFilterQuality;
1742 
1743   auto paint_image =
1744       CreateDiscardablePaintImage(gfx::Size(min_dimension, min_dimension),
1745                                   DefaultColorSpace().ToSkColorSpace(), false);
1746   DrawImage draw_image(paint_image, false, SkIRect::MakeXYWH(0, 0, 10, 10),
1747                        quality,
1748                        CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1749                        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1750 
1751   ImageDecodeCache::TaskResult result =
1752       cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1753   EXPECT_TRUE(result.task);
1754   EXPECT_TRUE(result.need_unref);
1755 
1756   TestTileTaskRunner::ProcessTask(result.task.get());
1757 
1758   DecodedDrawImage decoded_draw_image =
1759       cache.GetDecodedImageForDraw(draw_image);
1760   // Since we didn't allocate any backing for the memory, we expect this to be
1761   // false. This test is here to ensure that we at least got to the point where
1762   // we tried to decode something instead of recursing infinitely.
1763   EXPECT_FALSE(decoded_draw_image.image());
1764   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1765   cache.UnrefImage(draw_image);
1766 }
1767 
TEST(SoftwareImageDecodeCacheTest,EmptyTargetSizeDecode)1768 TEST(SoftwareImageDecodeCacheTest, EmptyTargetSizeDecode) {
1769   // Tests that requesting an empty sized decode followed by an original sized
1770   // decode returns no decoded images. This is a regression test. See
1771   // crbug.com/802976.
1772 
1773   TestSoftwareImageDecodeCache cache;
1774   bool is_decomposable = true;
1775   SkFilterQuality quality = kLow_SkFilterQuality;
1776 
1777   // Populate the cache with an original sized decode.
1778   auto paint_image = CreateDiscardablePaintImage(
1779       gfx::Size(100, 100), DefaultColorSpace().ToSkColorSpace());
1780   DrawImage draw_image(paint_image, false, SkIRect::MakeWH(100, 100), quality,
1781                        CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1782                        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1783   DecodedDrawImage decoded_draw_image =
1784       cache.GetDecodedImageForDraw(draw_image);
1785   EXPECT_TRUE(decoded_draw_image.image());
1786   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1787 
1788   // Ask for another decode, this time with an empty subrect.
1789   DrawImage empty_draw_image(
1790       paint_image, false, SkIRect::MakeEmpty(), quality,
1791       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1792       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1793   DecodedDrawImage empty_decoded_draw_image =
1794       cache.GetDecodedImageForDraw(empty_draw_image);
1795   EXPECT_FALSE(empty_decoded_draw_image.image());
1796   cache.DrawWithImageFinished(empty_draw_image, empty_decoded_draw_image);
1797 }
1798 
TEST(SoftwareImageDecodeCacheTest,BitmapImageColorConverted)1799 TEST(SoftwareImageDecodeCacheTest, BitmapImageColorConverted) {
1800   TestSoftwareImageDecodeCache cache;
1801   bool is_decomposable = true;
1802   SkFilterQuality quality = kHigh_SkFilterQuality;
1803   gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateDisplayP3D65();
1804 
1805   PaintImage paint_image = CreateBitmapImage(gfx::Size(100, 100));
1806   DrawImage draw_image(
1807       paint_image, false,
1808       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1809       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1810       PaintImage::kDefaultFrameIndex, target_color_space);
1811 
1812   DecodedDrawImage decoded_draw_image =
1813       cache.GetDecodedImageForDraw(draw_image);
1814   EXPECT_TRUE(decoded_draw_image.image());
1815   // Expect that we allocated a new image.
1816   EXPECT_NE(decoded_draw_image.image().get(), paint_image.GetSwSkImage().get());
1817   // Expect that the image color space match the target color space.
1818   EXPECT_TRUE(decoded_draw_image.image()->colorSpace());
1819   EXPECT_TRUE(SkColorSpace::Equals(decoded_draw_image.image()->colorSpace(),
1820                                    target_color_space.ToSkColorSpace().get()));
1821 
1822   cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1823 }
1824 
TEST(SoftwareImageDecodeCacheTest,BitmapImageNotColorConverted)1825 TEST(SoftwareImageDecodeCacheTest, BitmapImageNotColorConverted) {
1826   TestSoftwareImageDecodeCache cache;
1827   bool is_decomposable = true;
1828   SkFilterQuality quality = kHigh_SkFilterQuality;
1829 
1830   PaintImage paint_image = CreateBitmapImage(gfx::Size(100, 100));
1831   DrawImage draw_image(
1832       paint_image, false,
1833       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1834       CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1835       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1836 
1837   // The cache should not support this image.
1838   EXPECT_FALSE(cache.UseCacheForDrawImage(draw_image));
1839 }
1840 
1841 // TODO(ccameron): Re-enable this when the root cause of crashes is discovered.
1842 // https://crbug.com/791828
TEST(SoftwareImageDecodeCacheTest,DISABLED_ContentIdCaching)1843 TEST(SoftwareImageDecodeCacheTest, DISABLED_ContentIdCaching) {
1844   TestSoftwareImageDecodeCache cache;
1845   bool is_decomposable = true;
1846   SkFilterQuality quality = kHigh_SkFilterQuality;
1847   PaintImage::Id stable_id = 1001;
1848 
1849   for (int i = 0; i < 10; ++i) {
1850     // Create several images with the same stable id, but new content ids.
1851     PaintImage paint_image = CreateDiscardablePaintImage(
1852         gfx::Size(100, 100), nullptr, true, stable_id);
1853 
1854     // Cache two entries of different scales.
1855     for (int j = 0; j < 2; ++j) {
1856       float scale = j == 0 ? 1.f : 0.5f;
1857       DrawImage draw_image(
1858           paint_image, false,
1859           SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1860           CreateMatrix(SkSize::Make(scale, scale), is_decomposable),
1861           PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1862       DecodedDrawImage decoded_draw_image =
1863           cache.GetDecodedImageForDraw(draw_image);
1864       EXPECT_TRUE(decoded_draw_image.image());
1865       cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1866     }
1867 
1868     // After the first two entries come in, we start evicting old content ids.
1869     if (i == 0)
1870       EXPECT_LE(cache.GetNumCacheEntriesForTesting(), 2u);
1871     else
1872       EXPECT_LE(cache.GetNumCacheEntriesForTesting(), 4u);
1873   }
1874 }
1875 
TEST(SoftwareImageDecodeCacheTest,DecodeToScale)1876 TEST(SoftwareImageDecodeCacheTest, DecodeToScale) {
1877   TestSoftwareImageDecodeCache cache;
1878   bool is_decomposable = true;
1879   SkFilterQuality quality = kMedium_SkFilterQuality;
1880 
1881   SkISize full_size = SkISize::Make(100, 100);
1882   std::vector<SkISize> supported_sizes = {SkISize::Make(25, 25),
1883                                           SkISize::Make(50, 50)};
1884   std::vector<FrameMetadata> frames = {FrameMetadata()};
1885   sk_sp<FakePaintImageGenerator> generator =
1886       sk_make_sp<FakePaintImageGenerator>(
1887           SkImageInfo::MakeN32Premul(full_size.width(), full_size.height(),
1888                                      DefaultColorSpace().ToSkColorSpace()),
1889           frames, true, supported_sizes);
1890   PaintImage paint_image = PaintImageBuilder::WithDefault()
1891                                .set_id(PaintImage::GetNextId())
1892                                .set_paint_image_generator(generator)
1893                                .TakePaintImage();
1894 
1895   // Scale to mip level 1, there should be a single entry in the cache from
1896   // the direct decode.
1897   DrawImage draw_image1(
1898       paint_image, false,
1899       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1900       CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
1901       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1902   DecodedDrawImage decoded_image1 = cache.GetDecodedImageForDraw(draw_image1);
1903   ASSERT_TRUE(decoded_image1.image());
1904   EXPECT_EQ(decoded_image1.image()->width(), 50);
1905   EXPECT_EQ(decoded_image1.image()->height(), 50);
1906   EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 1u);
1907 
1908   // We should have requested a scaled decode from the generator.
1909   ASSERT_EQ(generator->decode_infos().size(), 1u);
1910   EXPECT_EQ(generator->decode_infos().at(0).width(), 50);
1911   EXPECT_EQ(generator->decode_infos().at(0).height(), 50);
1912 
1913   // Scale to mip level 2, we should be using the existing entry instead of
1914   // re-decoding.
1915   DrawImage draw_image2(
1916       paint_image, false,
1917       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1918       CreateMatrix(SkSize::Make(0.25, 0.25), is_decomposable),
1919       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1920   DecodedDrawImage decoded_image2 = cache.GetDecodedImageForDraw(draw_image2);
1921   ASSERT_TRUE(decoded_image2.image());
1922   EXPECT_EQ(decoded_image2.image()->width(), 25);
1923   EXPECT_EQ(decoded_image2.image()->height(), 25);
1924   EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 2u);
1925 
1926   // Since we scaled from the existing entry, no new decodes should be
1927   // requested from the generator.
1928   ASSERT_EQ(generator->decode_infos().size(), 1u);
1929   EXPECT_EQ(generator->decode_infos().at(0).width(), 50);
1930   EXPECT_EQ(generator->decode_infos().at(0).height(), 50);
1931 
1932   cache.DrawWithImageFinished(draw_image1, decoded_image1);
1933   cache.DrawWithImageFinished(draw_image2, decoded_image2);
1934 }
1935 
TEST(SoftwareImageDecodeCacheTest,DecodeToScaleSubrect)1936 TEST(SoftwareImageDecodeCacheTest, DecodeToScaleSubrect) {
1937   TestSoftwareImageDecodeCache cache;
1938   bool is_decomposable = true;
1939   SkFilterQuality quality = kMedium_SkFilterQuality;
1940 
1941   SkISize full_size = SkISize::Make(100, 100);
1942   std::vector<SkISize> supported_sizes = {SkISize::Make(25, 25),
1943                                           SkISize::Make(50, 50)};
1944   std::vector<FrameMetadata> frames = {FrameMetadata()};
1945   sk_sp<FakePaintImageGenerator> generator =
1946       sk_make_sp<FakePaintImageGenerator>(
1947           SkImageInfo::MakeN32Premul(full_size.width(), full_size.height(),
1948                                      DefaultColorSpace().ToSkColorSpace()),
1949           frames, true, supported_sizes);
1950   PaintImage paint_image = PaintImageBuilder::WithDefault()
1951                                .set_id(PaintImage::GetNextId())
1952                                .set_paint_image_generator(generator)
1953                                .TakePaintImage();
1954 
1955   // Scale to mip level 1, there should be 2 entries in the cache, since the
1956   // subrect vetoes decode to scale.
1957   DrawImage draw_image(paint_image, false, SkIRect::MakeWH(50, 50), quality,
1958                        CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
1959                        PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1960   DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
1961   ASSERT_TRUE(decoded_image.image());
1962   EXPECT_EQ(decoded_image.image()->width(), 25);
1963   EXPECT_EQ(decoded_image.image()->height(), 25);
1964   EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 2u);
1965 
1966   // We should have requested the original decode from the generator.
1967   ASSERT_EQ(generator->decode_infos().size(), 1u);
1968   EXPECT_EQ(generator->decode_infos().at(0).width(), 100);
1969   EXPECT_EQ(generator->decode_infos().at(0).height(), 100);
1970   cache.DrawWithImageFinished(draw_image, decoded_image);
1971 }
1972 
TEST(SoftwareImageDecodeCacheTest,DecodeToScaleNoneQuality)1973 TEST(SoftwareImageDecodeCacheTest, DecodeToScaleNoneQuality) {
1974   TestSoftwareImageDecodeCache cache;
1975   bool is_decomposable = true;
1976   SkFilterQuality quality = kNone_SkFilterQuality;
1977 
1978   SkISize full_size = SkISize::Make(100, 100);
1979   std::vector<SkISize> supported_sizes = {SkISize::Make(25, 25),
1980                                           SkISize::Make(50, 50)};
1981   std::vector<FrameMetadata> frames = {FrameMetadata()};
1982   sk_sp<FakePaintImageGenerator> generator =
1983       sk_make_sp<FakePaintImageGenerator>(
1984           SkImageInfo::MakeN32Premul(full_size.width(), full_size.height(),
1985                                      DefaultColorSpace().ToSkColorSpace()),
1986           frames, true, supported_sizes);
1987   PaintImage paint_image = PaintImageBuilder::WithDefault()
1988                                .set_id(PaintImage::GetNextId())
1989                                .set_paint_image_generator(generator)
1990                                .TakePaintImage();
1991 
1992   DrawImage draw_image(
1993       paint_image, false,
1994       SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1995       CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
1996       PaintImage::kDefaultFrameIndex, DefaultColorSpace());
1997   DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
1998   ASSERT_TRUE(decoded_image.image());
1999   EXPECT_EQ(decoded_image.image()->width(), 100);
2000   EXPECT_EQ(decoded_image.image()->height(), 100);
2001 
2002   // We should have requested the original decode from the generator.
2003   ASSERT_EQ(generator->decode_infos().size(), 1u);
2004   EXPECT_EQ(generator->decode_infos().at(0).width(), 100);
2005   EXPECT_EQ(generator->decode_infos().at(0).height(), 100);
2006   cache.DrawWithImageFinished(draw_image, decoded_image);
2007 }
2008 
TEST(SoftwareImageDecodeCacheTest,HdrDecodeToHdr)2009 TEST(SoftwareImageDecodeCacheTest, HdrDecodeToHdr) {
2010   TestSoftwareImageDecodeCache cache;
2011 
2012   auto color_space = gfx::ColorSpace::CreateHDR10();
2013   auto size = SkISize::Make(100, 100);
2014   auto info =
2015       SkImageInfo::Make(size.width(), size.height(), kRGBA_F16_SkColorType,
2016                         kPremul_SkAlphaType, color_space.ToSkColorSpace());
2017   SkBitmap bitmap;
2018   bitmap.allocPixels(info);
2019   PaintImage image = PaintImageBuilder::WithDefault()
2020                          .set_id(PaintImage::kInvalidId)
2021                          .set_is_high_bit_depth(true)
2022                          .set_image(SkImage::MakeFromBitmap(bitmap),
2023                                     PaintImage::GetNextContentId())
2024                          .TakePaintImage();
2025 
2026   DrawImage draw_image(
2027       image, false, SkIRect::MakeWH(image.width(), image.height()),
2028       kMedium_SkFilterQuality, CreateMatrix(SkSize::Make(0.5, 0.5), true),
2029       PaintImage::kDefaultFrameIndex, color_space);
2030 
2031   DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
2032   EXPECT_EQ(decoded_image.image()->colorType(), kRGBA_F16_SkColorType);
2033   cache.DrawWithImageFinished(draw_image, decoded_image);
2034 }
2035 
TEST(SoftwareImageDecodeCacheTest,HdrDecodeToSdr)2036 TEST(SoftwareImageDecodeCacheTest, HdrDecodeToSdr) {
2037   TestSoftwareImageDecodeCache cache;
2038 
2039   auto image_color_space = gfx::ColorSpace::CreateHDR10();
2040   auto size = SkISize::Make(100, 100);
2041   auto info = SkImageInfo::Make(size.width(), size.height(),
2042                                 kRGBA_F16_SkColorType, kPremul_SkAlphaType,
2043                                 image_color_space.ToSkColorSpace());
2044   SkBitmap bitmap;
2045   bitmap.allocPixels(info);
2046   PaintImage image = PaintImageBuilder::WithDefault()
2047                          .set_id(PaintImage::kInvalidId)
2048                          .set_is_high_bit_depth(true)
2049                          .set_image(SkImage::MakeFromBitmap(bitmap),
2050                                     PaintImage::GetNextContentId())
2051                          .TakePaintImage();
2052 
2053   // Note: We use P3 here since software cache shouldn't be used when conversion
2054   // to SRGB is needed.
2055   auto raster_color_space = gfx::ColorSpace::CreateDisplayP3D65();
2056   DrawImage draw_image(
2057       image, false, SkIRect::MakeWH(image.width(), image.height()),
2058       kMedium_SkFilterQuality, CreateMatrix(SkSize::Make(0.5, 0.5), true),
2059       PaintImage::kDefaultFrameIndex, raster_color_space);
2060 
2061   DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
2062   EXPECT_NE(decoded_image.image()->colorType(), kRGBA_F16_SkColorType);
2063   cache.DrawWithImageFinished(draw_image, decoded_image);
2064 }
2065 
2066 }  // namespace
2067 }  // namespace cc
2068