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