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