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