1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/tiles/software_image_decode_cache.h"
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"
18 TargetColorParams DefaultTargetColorParams() {
19 return TargetColorParams();
22 sk_sp<SkColorSpace> DefaultSkColorSpace() {
23 return DefaultTargetColorParams().color_space.ToSkColorSpace();
26 size_t kLockedMemoryLimitBytes = 128 * 1024 * 1024;
27 class TestSoftwareImageDecodeCache : public SoftwareImageDecodeCache {
29 TestSoftwareImageDecodeCache()
30 : SoftwareImageDecodeCache(kN32_SkColorType, kLockedMemoryLimitBytes) {}
33 SkM44 CreateMatrix(const SkSize& scale, bool is_decomposable) {
34 SkM44 matrix = SkM44::Scale(scale.width(), scale.height());
36 if (!is_decomposable) {
37 // Perspective is not decomposable, add it.
38 matrix.setRC(3, 0, 0.1f);
44 PaintImage CreatePaintImage(int width, int height) {
45 return CreateDiscardablePaintImage(gfx::Size(width, height),
46 DefaultSkColorSpace());
49 PaintImage CreatePaintImage(int width,
51 const TargetColorParams& target_color_params) {
52 return CreateDiscardablePaintImage(
53 gfx::Size(width, height),
54 target_color_params.color_space.ToSkColorSpace());
57 TEST(SoftwareImageDecodeCacheTest, ImageKeyNoneQuality) {
58 PaintImage paint_image = CreatePaintImage(100, 100);
59 bool is_decomposable = true;
62 SkIRect::MakeWH(paint_image.width(), paint_image.height()),
63 PaintFlags::FilterQuality::kNone,
64 CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
65 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
67 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
68 draw_image, kN32_SkColorType);
69 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
70 EXPECT_TRUE(key.is_nearest_neighbor());
71 EXPECT_EQ(100, key.target_size().width());
72 EXPECT_EQ(100, key.target_size().height());
73 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
74 // Since the original decode will be used, the locked_bytes is that of the
76 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
79 TEST(SoftwareImageDecodeCacheTest,
80 ImageKeyLowQualityIncreasedToMediumIfDownscale) {
81 PaintImage paint_image = CreatePaintImage(100, 100);
82 bool is_decomposable = true;
85 SkIRect::MakeWH(paint_image.width(), paint_image.height()),
86 PaintFlags::FilterQuality::kLow,
87 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
88 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
90 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
91 draw_image, kN32_SkColorType);
92 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
93 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
94 EXPECT_EQ(50, key.target_size().width());
95 EXPECT_EQ(50, key.target_size().height());
96 EXPECT_EQ(50u * 50u * 4u, key.locked_bytes());
99 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropsToLowIfMipLevel0) {
100 PaintImage paint_image = CreatePaintImage(100, 100);
101 bool is_decomposable = true;
102 DrawImage draw_image(
104 SkIRect::MakeWH(paint_image.width(), paint_image.height()),
105 PaintFlags::FilterQuality::kMedium,
106 CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
107 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
109 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
110 draw_image, kN32_SkColorType);
111 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
112 EXPECT_FALSE(key.is_nearest_neighbor());
113 EXPECT_EQ(100, key.target_size().width());
114 EXPECT_EQ(100, key.target_size().height());
115 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
116 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
119 TEST(SoftwareImageDecodeCacheTest, LowUnscalableFormatStaysLow) {
120 PaintImage paint_image = CreatePaintImage(100, 100);
121 bool is_decomposable = true;
122 DrawImage draw_image(
124 SkIRect::MakeWH(paint_image.width(), paint_image.height()),
125 PaintFlags::FilterQuality::kLow,
126 CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
127 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
129 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
130 draw_image, kARGB_4444_SkColorType);
131 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
132 EXPECT_FALSE(key.is_nearest_neighbor());
133 EXPECT_EQ(100, key.target_size().width());
134 EXPECT_EQ(100, key.target_size().height());
135 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
136 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
139 TEST(SoftwareImageDecodeCacheTest, HighUnscalableFormatBecomesLow) {
140 PaintImage paint_image = CreatePaintImage(100, 100);
141 bool is_decomposable = true;
142 DrawImage draw_image(
144 SkIRect::MakeWH(paint_image.width(), paint_image.height()),
145 PaintFlags::FilterQuality::kHigh,
146 CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
147 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
149 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
150 draw_image, kARGB_4444_SkColorType);
151 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
152 EXPECT_FALSE(key.is_nearest_neighbor());
153 EXPECT_EQ(100, key.target_size().width());
154 EXPECT_EQ(100, key.target_size().height());
155 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
156 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
159 TEST(SoftwareImageDecodeCacheTest, ImageKeyLowQualityKeptLowIfUpscale) {
160 PaintImage paint_image = CreatePaintImage(100, 100);
161 bool is_decomposable = true;
162 DrawImage draw_image(
164 SkIRect::MakeWH(paint_image.width(), paint_image.height()),
165 PaintFlags::FilterQuality::kLow,
166 CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
167 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
169 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
170 draw_image, kN32_SkColorType);
171 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
172 EXPECT_FALSE(key.is_nearest_neighbor());
173 EXPECT_EQ(100, key.target_size().width());
174 EXPECT_EQ(100, key.target_size().height());
175 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
176 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
179 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQuality) {
180 PaintImage paint_image = CreatePaintImage(100, 100);
181 bool is_decomposable = true;
182 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
184 DrawImage draw_image(
186 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
187 CreateMatrix(SkSize::Make(0.5f, 0.4f), is_decomposable),
188 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
190 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
191 draw_image, kN32_SkColorType);
192 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
193 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
194 EXPECT_EQ(50, key.target_size().width());
195 EXPECT_EQ(50, key.target_size().height());
196 EXPECT_EQ(50u * 50u * 4u, key.locked_bytes());
199 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropToLowIfEnlarging) {
200 PaintImage paint_image = CreatePaintImage(100, 100);
201 bool is_decomposable = true;
202 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
204 DrawImage draw_image(
206 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
207 CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
208 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
210 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
211 draw_image, kN32_SkColorType);
212 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
213 EXPECT_FALSE(key.is_nearest_neighbor());
214 EXPECT_EQ(100, key.target_size().width());
215 EXPECT_EQ(100, key.target_size().height());
216 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
217 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
220 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropToLowIfIdentity) {
221 PaintImage paint_image = CreatePaintImage(100, 100);
222 bool is_decomposable = true;
223 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
225 DrawImage draw_image(
227 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
228 CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
229 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
231 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
232 draw_image, kN32_SkColorType);
233 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
234 EXPECT_FALSE(key.is_nearest_neighbor());
235 EXPECT_EQ(100, key.target_size().width());
236 EXPECT_EQ(100, key.target_size().height());
237 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
238 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
241 TEST(SoftwareImageDecodeCacheTest,
242 ImageKeyMediumQualityDropToLowIfNearlyIdentity) {
243 PaintImage paint_image = CreatePaintImage(100, 100);
244 bool is_decomposable = true;
245 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
247 DrawImage draw_image(
249 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
250 CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
251 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
253 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
254 draw_image, kN32_SkColorType);
255 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
256 EXPECT_FALSE(key.is_nearest_neighbor());
257 EXPECT_EQ(100, key.target_size().width());
258 EXPECT_EQ(100, key.target_size().height());
259 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
260 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
263 TEST(SoftwareImageDecodeCacheTest,
264 ImageKeyMediumQualityDropToLowIfNearlyIdentity2) {
265 PaintImage paint_image = CreatePaintImage(100, 100);
266 bool is_decomposable = true;
267 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
269 DrawImage draw_image(
271 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
272 CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
273 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
275 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
276 draw_image, kN32_SkColorType);
277 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
278 EXPECT_FALSE(key.is_nearest_neighbor());
279 EXPECT_EQ(100, key.target_size().width());
280 EXPECT_EQ(100, key.target_size().height());
281 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
282 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
285 TEST(SoftwareImageDecodeCacheTest,
286 ImageKeyMediumQualityDropToLowIfNotDecomposable) {
287 PaintImage paint_image = CreatePaintImage(100, 100);
288 bool is_decomposable = false;
289 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
291 DrawImage draw_image(
293 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
294 CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
295 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
297 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
298 draw_image, kN32_SkColorType);
299 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
301 EXPECT_FALSE(key.is_nearest_neighbor());
302 EXPECT_EQ(100, key.target_size().width());
303 EXPECT_EQ(100, key.target_size().height());
304 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
305 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
308 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt1_5Scale) {
309 PaintImage paint_image = CreatePaintImage(500, 200);
310 bool is_decomposable = true;
311 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
313 DrawImage draw_image(
315 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
316 CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
317 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
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());
329 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt1_0cale) {
330 PaintImage paint_image = CreatePaintImage(500, 200);
331 bool is_decomposable = true;
332 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
334 DrawImage draw_image(
336 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
337 CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
338 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
340 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
341 draw_image, kN32_SkColorType);
342 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
343 EXPECT_FALSE(key.is_nearest_neighbor());
344 EXPECT_EQ(500, key.target_size().width());
345 EXPECT_EQ(200, key.target_size().height());
346 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
347 EXPECT_EQ(500u * 200u * 4u, key.locked_bytes());
350 TEST(SoftwareImageDecodeCacheTest, ImageKeyLowQualityAt0_75Scale) {
351 PaintImage paint_image = CreatePaintImage(500, 200);
352 bool is_decomposable = true;
353 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
355 DrawImage draw_image(
357 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
358 CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
359 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
361 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
362 draw_image, kN32_SkColorType);
363 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
364 EXPECT_FALSE(key.is_nearest_neighbor());
365 EXPECT_EQ(500, key.target_size().width());
366 EXPECT_EQ(200, key.target_size().height());
367 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
368 EXPECT_EQ(500u * 200u * 4u, key.locked_bytes());
371 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_5Scale) {
372 PaintImage paint_image = CreatePaintImage(500, 200);
373 bool is_decomposable = true;
374 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
376 DrawImage draw_image(
378 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
379 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
380 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
382 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
383 draw_image, kN32_SkColorType);
384 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
385 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
386 EXPECT_EQ(250, key.target_size().width());
387 EXPECT_EQ(100, key.target_size().height());
388 EXPECT_EQ(250u * 100u * 4u, key.locked_bytes());
391 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_49Scale) {
392 PaintImage paint_image = CreatePaintImage(500, 200);
393 bool is_decomposable = true;
394 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
396 DrawImage draw_image(
398 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
399 CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
400 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
402 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
403 draw_image, kN32_SkColorType);
404 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
405 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
406 EXPECT_EQ(250, key.target_size().width());
407 EXPECT_EQ(100, key.target_size().height());
408 EXPECT_EQ(250u * 100u * 4u, key.locked_bytes());
411 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_1Scale) {
412 PaintImage paint_image = CreatePaintImage(500, 200);
413 bool is_decomposable = true;
414 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
416 DrawImage draw_image(
418 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
419 CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
420 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
422 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
423 draw_image, kN32_SkColorType);
424 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
425 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
426 EXPECT_EQ(63, key.target_size().width());
427 EXPECT_EQ(25, key.target_size().height());
428 EXPECT_EQ(63u * 25u * 4u, key.locked_bytes());
431 TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_01Scale) {
432 PaintImage paint_image = CreatePaintImage(500, 200);
433 bool is_decomposable = true;
434 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
436 DrawImage draw_image(
438 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
439 CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
440 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
442 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
443 draw_image, kN32_SkColorType);
444 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
445 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
446 EXPECT_EQ(8, key.target_size().width());
447 EXPECT_EQ(4, key.target_size().height());
448 EXPECT_EQ(8u * 4u * 4u, key.locked_bytes());
451 TEST(SoftwareImageDecodeCacheTest,
452 ImageKeyFullDowscalesDropsHighQualityToMedium) {
453 PaintImage paint_image = CreatePaintImage(100, 100);
454 bool is_decomposable = true;
455 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
457 DrawImage draw_image(
459 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
460 CreateMatrix(SkSize::Make(0.5f, 0.2f), is_decomposable),
461 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
463 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
464 draw_image, kN32_SkColorType);
465 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
466 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
467 EXPECT_EQ(50, key.target_size().width());
468 EXPECT_EQ(50, key.target_size().height());
469 EXPECT_EQ(50u * 50u * 4u, key.locked_bytes());
472 TEST(SoftwareImageDecodeCacheTest, ImageKeyUpscaleIsLowQuality) {
473 PaintImage paint_image = CreatePaintImage(100, 100);
474 bool is_decomposable = true;
475 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
477 DrawImage draw_image(
479 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
480 CreateMatrix(SkSize::Make(2.5f, 1.5f), is_decomposable),
481 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
483 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
484 draw_image, kN32_SkColorType);
485 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
486 EXPECT_FALSE(key.is_nearest_neighbor());
487 EXPECT_EQ(100, key.target_size().width());
488 EXPECT_EQ(100, key.target_size().height());
489 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
490 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
493 TEST(SoftwareImageDecodeCacheTest, ImageKeyHighQualityDropToMediumIfTooLarge) {
494 // Just over 64MB when scaled.
495 PaintImage paint_image = CreatePaintImage(4555, 2048);
496 bool is_decomposable = true;
497 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
499 // At least one dimension should scale down, so that medium quality doesn't
501 DrawImage draw_image(
503 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
504 CreateMatrix(SkSize::Make(0.45f, 0.45f), is_decomposable),
505 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
507 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
508 draw_image, kN32_SkColorType);
509 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
510 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
511 EXPECT_EQ(2278, key.target_size().width());
512 EXPECT_EQ(1024, key.target_size().height());
513 EXPECT_EQ(2278u * 1024u * 4u, key.locked_bytes());
516 TEST(SoftwareImageDecodeCacheTest,
517 ImageKeyHighQualityDropToLowIfNotDecomposable) {
518 PaintImage paint_image = CreatePaintImage(100, 100);
519 bool is_decomposable = false;
520 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
522 DrawImage draw_image(
524 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
525 CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
526 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
528 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
529 draw_image, kN32_SkColorType);
530 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
531 EXPECT_FALSE(key.is_nearest_neighbor());
532 EXPECT_EQ(100, key.target_size().width());
533 EXPECT_EQ(100, key.target_size().height());
534 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
535 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
538 TEST(SoftwareImageDecodeCacheTest, ImageKeyHighQualityDropToLowIfIdentity) {
539 PaintImage paint_image = CreatePaintImage(100, 100);
540 bool is_decomposable = true;
541 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
543 DrawImage draw_image(
545 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
546 CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
547 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
549 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
550 draw_image, kN32_SkColorType);
551 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
552 EXPECT_FALSE(key.is_nearest_neighbor());
553 EXPECT_EQ(100, key.target_size().width());
554 EXPECT_EQ(100, key.target_size().height());
555 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
556 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
559 TEST(SoftwareImageDecodeCacheTest,
560 ImageKeyHighQualityDropToLowIfNearlyIdentity) {
561 PaintImage paint_image = CreatePaintImage(100, 100);
562 bool is_decomposable = true;
563 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
565 DrawImage draw_image(
567 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
568 CreateMatrix(SkSize::Make(1.001f, 1.001f), is_decomposable),
569 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
571 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
572 draw_image, kN32_SkColorType);
573 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
574 EXPECT_FALSE(key.is_nearest_neighbor());
575 EXPECT_EQ(100, key.target_size().width());
576 EXPECT_EQ(100, key.target_size().height());
577 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
578 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
581 TEST(SoftwareImageDecodeCacheTest,
582 ImageKeyHighQualityDropToLowIfNearlyIdentity2) {
583 PaintImage paint_image = CreatePaintImage(100, 100);
584 bool is_decomposable = true;
585 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
587 DrawImage draw_image(
589 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
590 CreateMatrix(SkSize::Make(0.999f, 0.999f), is_decomposable),
591 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
593 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
594 draw_image, kN32_SkColorType);
595 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
596 EXPECT_FALSE(key.is_nearest_neighbor());
597 EXPECT_EQ(100, key.target_size().width());
598 EXPECT_EQ(100, key.target_size().height());
599 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
600 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
603 TEST(SoftwareImageDecodeCacheTest, ImageKeyDownscaleMipLevelWithRounding) {
604 // Tests that, when using a non-zero mip level, the final target size (which
605 // is the size of the chosen mip level) is as expected if rounding is
608 // The 97x61 dimensions and the (0.2f, 0.2f) scaling were chosen specifically
611 // - The starting target size is 19x12 which means that 2 is the chosen mip
614 // - Attempting to get the final target size by simply multiplying the
615 // dimensions of the |src_rect| (97x61) times
616 // MipMapUtil::GetScaleAdjustmentForLevel() yields 24x15 if we attempt to
617 // store the result as integers. This is inconsistent with the rounding
618 // behavior introduced in https://crrev.com/c/1107049 and was the cause of
619 // https://crbug.com/891316.
620 PaintImage paint_image = CreatePaintImage(97, 61);
621 bool is_decomposable = true;
622 DrawImage draw_image(
624 SkIRect::MakeWH(paint_image.width(), paint_image.height()),
625 PaintFlags::FilterQuality::kMedium,
626 CreateMatrix(SkSize::Make(0.2f, 0.2f), is_decomposable),
627 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
629 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
630 draw_image, kN32_SkColorType);
631 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
632 EXPECT_FALSE(key.is_nearest_neighbor());
633 EXPECT_EQ(25, key.target_size().width());
634 EXPECT_EQ(16, key.target_size().height());
635 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
636 EXPECT_EQ(25u * 16u * 4u, key.locked_bytes());
639 TEST(SoftwareImageDecodeCacheTest, OriginalDecodesAreEqual) {
640 PaintImage paint_image = CreatePaintImage(100, 100);
641 bool is_decomposable = true;
642 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kNone;
644 DrawImage draw_image(
646 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
647 CreateMatrix(SkSize::Make(0.5f, 0.5), is_decomposable),
648 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
650 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
651 draw_image, kN32_SkColorType);
652 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
653 EXPECT_TRUE(key.is_nearest_neighbor());
654 EXPECT_EQ(100, key.target_size().width());
655 EXPECT_EQ(100, key.target_size().height());
656 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
657 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
659 DrawImage another_draw_image(
661 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
662 CreateMatrix(SkSize::Make(1.5f, 1.5), is_decomposable),
663 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
665 auto another_key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
666 another_draw_image, kN32_SkColorType);
667 EXPECT_EQ(another_draw_image.frame_key(), another_key.frame_key());
668 EXPECT_TRUE(another_key.is_nearest_neighbor());
669 EXPECT_EQ(100, another_key.target_size().width());
670 EXPECT_EQ(100, another_key.target_size().height());
671 EXPECT_EQ(another_key.type(), SoftwareImageDecodeCache::CacheKey::kOriginal);
672 EXPECT_EQ(100u * 100u * 4u, another_key.locked_bytes());
674 EXPECT_TRUE(key == another_key);
677 TEST(SoftwareImageDecodeCacheTest, ImageRectDoesNotContainSrcRect) {
678 PaintImage paint_image = CreatePaintImage(100, 100);
679 bool is_decomposable = true;
680 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
682 DrawImage draw_image(
684 SkIRect::MakeXYWH(25, 35, paint_image.width(), paint_image.height()),
685 quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
686 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
688 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
689 draw_image, kN32_SkColorType);
690 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
691 EXPECT_FALSE(key.is_nearest_neighbor());
692 EXPECT_EQ(100, key.target_size().width());
693 EXPECT_EQ(100, key.target_size().height());
694 EXPECT_EQ(gfx::Rect(25, 35, 75, 65), key.src_rect());
695 EXPECT_EQ(100u * 100u * 4u, key.locked_bytes());
698 TEST(SoftwareImageDecodeCacheTest, ImageRectDoesNotContainSrcRectWithScale) {
699 PaintImage paint_image = CreatePaintImage(100, 100);
700 bool is_decomposable = true;
701 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
703 DrawImage draw_image(
705 SkIRect::MakeXYWH(20, 30, paint_image.width(), paint_image.height()),
706 quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
707 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
709 auto key = SoftwareImageDecodeCache::CacheKey::FromDrawImage(
710 draw_image, kN32_SkColorType);
711 EXPECT_EQ(draw_image.frame_key(), key.frame_key());
712 EXPECT_EQ(key.type(), SoftwareImageDecodeCache::CacheKey::kSubrectAndScale);
713 EXPECT_EQ(40, key.target_size().width());
714 EXPECT_EQ(35, key.target_size().height());
715 EXPECT_EQ(gfx::Rect(20, 30, 80, 70), key.src_rect());
716 EXPECT_EQ(40u * 35u * 4u, key.locked_bytes());
719 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImage) {
720 TestSoftwareImageDecodeCache cache;
721 PaintImage paint_image = CreatePaintImage(100, 100);
722 bool is_decomposable = true;
723 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
725 DrawImage draw_image(
727 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
728 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
729 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
730 ImageDecodeCache::TaskResult result =
731 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
732 EXPECT_TRUE(result.need_unref);
733 EXPECT_TRUE(result.task);
735 DrawImage another_draw_image(
737 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
738 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
739 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
740 ImageDecodeCache::TaskResult another_result = cache.GetTaskForImageAndRef(
741 another_draw_image, ImageDecodeCache::TracingInfo());
742 EXPECT_TRUE(another_result.need_unref);
743 EXPECT_TRUE(result.task.get() == another_result.task.get());
745 TestTileTaskRunner::ProcessTask(result.task.get());
747 cache.UnrefImage(draw_image);
748 cache.UnrefImage(draw_image);
751 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageProcessUnrefCancel) {
752 TestSoftwareImageDecodeCache cache;
753 PaintImage paint_image = CreatePaintImage(100, 100);
754 bool is_decomposable = true;
755 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
757 DrawImage draw_image(
759 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
760 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
761 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
762 ImageDecodeCache::TaskResult result =
763 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
764 EXPECT_TRUE(result.need_unref);
765 EXPECT_TRUE(result.task);
767 TestTileTaskRunner::ProcessTask(result.task.get());
768 cache.UnrefImage(draw_image);
771 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
772 EXPECT_TRUE(result.need_unref);
773 EXPECT_TRUE(result.task);
775 TestTileTaskRunner::CancelTask(result.task.get());
776 TestTileTaskRunner::CompleteTask(result.task.get());
777 // This is expected to pass instead of DCHECKing since we're reducing the ref
778 // for an image which isn't locked to begin with.
779 cache.UnrefImage(draw_image);
782 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentQuality) {
783 TestSoftwareImageDecodeCache cache;
784 PaintImage paint_image = CreatePaintImage(100, 100);
785 bool is_decomposable = true;
787 DrawImage high_quality_draw_image(
789 SkIRect::MakeWH(paint_image.width(), paint_image.height()),
790 PaintFlags::FilterQuality::kHigh,
791 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
792 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
793 ImageDecodeCache::TaskResult high_quality_result =
794 cache.GetTaskForImageAndRef(high_quality_draw_image,
795 ImageDecodeCache::TracingInfo());
796 EXPECT_TRUE(high_quality_result.need_unref);
797 EXPECT_TRUE(high_quality_result.task);
799 DrawImage none_quality_draw_image(
801 SkIRect::MakeWH(paint_image.width(), paint_image.height()),
802 PaintFlags::FilterQuality::kNone,
803 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
804 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
805 ImageDecodeCache::TaskResult none_quality_result =
806 cache.GetTaskForImageAndRef(none_quality_draw_image,
807 ImageDecodeCache::TracingInfo());
808 EXPECT_TRUE(none_quality_result.need_unref);
809 EXPECT_TRUE(none_quality_result.task);
810 EXPECT_TRUE(high_quality_result.task.get() != none_quality_result.task.get());
812 TestTileTaskRunner::ProcessTask(high_quality_result.task.get());
813 TestTileTaskRunner::ProcessTask(none_quality_result.task.get());
815 cache.UnrefImage(high_quality_draw_image);
816 cache.UnrefImage(none_quality_draw_image);
819 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentSize) {
820 TestSoftwareImageDecodeCache cache;
821 PaintImage paint_image = CreatePaintImage(100, 100);
822 bool is_decomposable = true;
823 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
825 DrawImage half_size_draw_image(
827 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
828 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
829 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
830 ImageDecodeCache::TaskResult half_size_result = cache.GetTaskForImageAndRef(
831 half_size_draw_image, ImageDecodeCache::TracingInfo());
832 EXPECT_TRUE(half_size_result.need_unref);
833 EXPECT_TRUE(half_size_result.task);
835 DrawImage quarter_size_draw_image(
837 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
838 CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
839 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
840 ImageDecodeCache::TaskResult quarter_size_result =
841 cache.GetTaskForImageAndRef(quarter_size_draw_image,
842 ImageDecodeCache::TracingInfo());
843 EXPECT_TRUE(quarter_size_result.need_unref);
844 EXPECT_TRUE(quarter_size_result.task);
845 EXPECT_TRUE(half_size_result.task.get() != quarter_size_result.task.get());
847 TestTileTaskRunner::ProcessTask(half_size_result.task.get());
848 TestTileTaskRunner::ProcessTask(quarter_size_result.task.get());
850 cache.UnrefImage(half_size_draw_image);
851 cache.UnrefImage(quarter_size_draw_image);
854 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentImage) {
855 TestSoftwareImageDecodeCache cache;
856 bool is_decomposable = true;
857 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
859 PaintImage first_paint_image = CreatePaintImage(100, 100);
860 DrawImage first_draw_image(
861 first_paint_image, false,
862 SkIRect::MakeWH(first_paint_image.width(), first_paint_image.height()),
863 quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
864 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
865 ImageDecodeCache::TaskResult first_result = cache.GetTaskForImageAndRef(
866 first_draw_image, ImageDecodeCache::TracingInfo());
867 EXPECT_TRUE(first_result.need_unref);
868 EXPECT_TRUE(first_result.task);
870 PaintImage second_paint_image = CreatePaintImage(100, 100);
871 DrawImage second_draw_image(
872 second_paint_image, false,
873 SkIRect::MakeWH(second_paint_image.width(), second_paint_image.height()),
874 quality, CreateMatrix(SkSize::Make(0.25f, 0.25f), is_decomposable),
875 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
876 ImageDecodeCache::TaskResult second_result = cache.GetTaskForImageAndRef(
877 second_draw_image, ImageDecodeCache::TracingInfo());
878 EXPECT_TRUE(second_result.need_unref);
879 EXPECT_TRUE(second_result.task);
880 EXPECT_TRUE(first_result.task.get() != second_result.task.get());
882 TestTileTaskRunner::ProcessTask(first_result.task.get());
883 TestTileTaskRunner::ProcessTask(second_result.task.get());
885 cache.UnrefImage(first_draw_image);
886 cache.UnrefImage(second_draw_image);
890 #if defined(MEMORY_SANITIZER)
891 #define MAYBE_GetTaskForImageDifferentColorSpace \
892 DISABLED_GetTaskForImageDifferentColorSpace
894 #define MAYBE_GetTaskForImageDifferentColorSpace \
895 GetTaskForImageDifferentColorSpace
897 TEST(SoftwareImageDecodeCacheTest, MAYBE_GetTaskForImageDifferentColorSpace) {
898 TestSoftwareImageDecodeCache cache;
899 bool is_decomposable = true;
900 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
902 TargetColorParams target_color_params_a(gfx::ColorSpace(
903 gfx::ColorSpace::PrimaryID::XYZ_D50, gfx::ColorSpace::TransferID::SRGB));
905 TargetColorParams target_color_params_b(
906 gfx::ColorSpace(gfx::ColorSpace::PrimaryID::SMPTE170M,
907 gfx::ColorSpace::TransferID::SRGB));
909 TargetColorParams target_color_params_c(gfx::ColorSpace::CreateSRGB());
911 PaintImage paint_image = CreatePaintImage(100, 100, target_color_params_a);
912 DrawImage first_draw_image(
914 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
915 CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
916 PaintImage::kDefaultFrameIndex, target_color_params_b);
917 ImageDecodeCache::TaskResult first_result = cache.GetTaskForImageAndRef(
918 first_draw_image, ImageDecodeCache::TracingInfo());
919 EXPECT_TRUE(first_result.need_unref);
920 EXPECT_TRUE(first_result.task);
922 DrawImage second_draw_image(
924 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
925 CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
926 PaintImage::kDefaultFrameIndex, target_color_params_c);
927 ImageDecodeCache::TaskResult second_result = cache.GetTaskForImageAndRef(
928 second_draw_image, ImageDecodeCache::TracingInfo());
929 EXPECT_TRUE(second_result.need_unref);
930 EXPECT_TRUE(second_result.task);
931 EXPECT_TRUE(first_result.task.get() != second_result.task.get());
933 DrawImage third_draw_image(
935 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
936 CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
937 PaintImage::kDefaultFrameIndex, target_color_params_b);
938 ImageDecodeCache::TaskResult third_result = cache.GetTaskForImageAndRef(
939 third_draw_image, ImageDecodeCache::TracingInfo());
940 EXPECT_TRUE(third_result.need_unref);
941 EXPECT_TRUE(third_result.task);
942 EXPECT_TRUE(first_result.task.get() == third_result.task.get());
944 TestTileTaskRunner::ProcessTask(first_result.task.get());
945 TestTileTaskRunner::ProcessTask(second_result.task.get());
947 cache.UnrefImage(first_draw_image);
948 cache.UnrefImage(second_draw_image);
949 cache.UnrefImage(third_draw_image);
952 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyDecoded) {
953 TestSoftwareImageDecodeCache cache;
954 bool is_decomposable = true;
955 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
957 PaintImage paint_image = CreatePaintImage(100, 100);
958 DrawImage draw_image(
960 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
961 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
962 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
963 ImageDecodeCache::TaskResult result =
964 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
965 EXPECT_TRUE(result.need_unref);
966 EXPECT_TRUE(result.task);
968 TestTileTaskRunner::ScheduleTask(result.task.get());
969 TestTileTaskRunner::RunTask(result.task.get());
971 ImageDecodeCache::TaskResult another_result =
972 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
973 EXPECT_TRUE(another_result.need_unref);
974 EXPECT_FALSE(another_result.task);
976 TestTileTaskRunner::CompleteTask(result.task.get());
978 cache.UnrefImage(draw_image);
979 cache.UnrefImage(draw_image);
982 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyPrerolled) {
983 TestSoftwareImageDecodeCache cache;
984 bool is_decomposable = true;
985 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kLow;
987 PaintImage paint_image = CreatePaintImage(100, 100);
988 DrawImage draw_image(
990 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
991 CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
992 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
993 ImageDecodeCache::TaskResult result =
994 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
995 EXPECT_TRUE(result.need_unref);
996 EXPECT_TRUE(result.task);
998 TestTileTaskRunner::ScheduleTask(result.task.get());
999 TestTileTaskRunner::RunTask(result.task.get());
1001 ImageDecodeCache::TaskResult another_result =
1002 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1003 EXPECT_TRUE(another_result.need_unref);
1004 EXPECT_FALSE(another_result.task);
1006 TestTileTaskRunner::CompleteTask(result.task.get());
1008 ImageDecodeCache::TaskResult third_result =
1009 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1010 EXPECT_TRUE(third_result.need_unref);
1011 EXPECT_FALSE(third_result.task);
1013 cache.UnrefImage(draw_image);
1014 cache.UnrefImage(draw_image);
1015 cache.UnrefImage(draw_image);
1018 TEST(SoftwareImageDecodeCacheTest, GetTaskForImageCanceledGetsNewTask) {
1019 TestSoftwareImageDecodeCache cache;
1020 bool is_decomposable = true;
1021 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
1023 PaintImage paint_image = CreatePaintImage(100, 100);
1024 DrawImage draw_image(
1026 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1027 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1028 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1029 ImageDecodeCache::TaskResult result =
1030 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1031 EXPECT_TRUE(result.need_unref);
1032 EXPECT_TRUE(result.task);
1034 ImageDecodeCache::TaskResult another_result =
1035 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1036 EXPECT_TRUE(another_result.need_unref);
1037 EXPECT_TRUE(another_result.task.get() == result.task.get());
1039 // Didn't run the task, complete it (it was canceled).
1040 TestTileTaskRunner::CancelTask(result.task.get());
1041 TestTileTaskRunner::CompleteTask(result.task.get());
1043 // Fully cancel everything (so the raster would unref things).
1044 cache.UnrefImage(draw_image);
1045 cache.UnrefImage(draw_image);
1047 // Here a new task is created.
1048 ImageDecodeCache::TaskResult third_result =
1049 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1050 EXPECT_TRUE(third_result.need_unref);
1051 EXPECT_TRUE(third_result.task);
1052 EXPECT_FALSE(third_result.task.get() == result.task.get());
1054 TestTileTaskRunner::ProcessTask(third_result.task.get());
1056 cache.UnrefImage(draw_image);
1059 TEST(SoftwareImageDecodeCacheTest,
1060 GetTaskForImageCanceledWhileReffedGetsNewTask) {
1061 TestSoftwareImageDecodeCache cache;
1062 bool is_decomposable = true;
1063 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
1065 PaintImage paint_image = CreatePaintImage(100, 100);
1066 DrawImage draw_image(
1068 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1069 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1070 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1071 ImageDecodeCache::TaskResult result =
1072 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1073 EXPECT_TRUE(result.need_unref);
1074 EXPECT_TRUE(result.task);
1076 ImageDecodeCache::TaskResult another_result =
1077 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1078 EXPECT_TRUE(another_result.need_unref);
1079 EXPECT_TRUE(another_result.task.get() == result.task.get());
1081 // Didn't run the task, complete it (it was canceled).
1082 TestTileTaskRunner::CancelTask(result.task.get());
1083 TestTileTaskRunner::CompleteTask(result.task.get());
1085 // Note that here, everything is reffed, but a new task is created. This is
1086 // possible with repeated schedule/cancel operations.
1087 ImageDecodeCache::TaskResult third_result =
1088 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1089 EXPECT_TRUE(third_result.need_unref);
1090 EXPECT_TRUE(third_result.task);
1091 EXPECT_FALSE(third_result.task.get() == result.task.get());
1093 TestTileTaskRunner::ProcessTask(third_result.task.get());
1096 cache.UnrefImage(draw_image);
1097 cache.UnrefImage(draw_image);
1098 cache.UnrefImage(draw_image);
1101 TEST(SoftwareImageDecodeCacheTest, GetDecodedImageForDraw) {
1102 TestSoftwareImageDecodeCache cache;
1103 bool is_decomposable = true;
1104 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
1106 PaintImage paint_image = CreatePaintImage(100, 100);
1107 DrawImage draw_image(
1109 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1110 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1111 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1112 ImageDecodeCache::TaskResult result =
1113 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1114 EXPECT_TRUE(result.need_unref);
1115 EXPECT_TRUE(result.task);
1117 TestTileTaskRunner::ProcessTask(result.task.get());
1119 DecodedDrawImage decoded_draw_image =
1120 cache.GetDecodedImageForDraw(draw_image);
1121 EXPECT_TRUE(decoded_draw_image.image());
1122 EXPECT_EQ(50, decoded_draw_image.image()->width());
1123 EXPECT_EQ(50, decoded_draw_image.image()->height());
1124 EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
1125 EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
1126 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1127 decoded_draw_image.filter_quality());
1128 EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
1130 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1131 cache.UnrefImage(draw_image);
1134 TEST(SoftwareImageDecodeCacheTest,
1135 GetDecodedImageForDrawWithNonContainedSrcRect) {
1136 TestSoftwareImageDecodeCache cache;
1137 bool is_decomposable = true;
1138 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
1140 PaintImage paint_image = CreatePaintImage(100, 100);
1141 DrawImage draw_image(
1143 SkIRect::MakeXYWH(20, 30, paint_image.width(), paint_image.height()),
1144 quality, CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1145 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1146 ImageDecodeCache::TaskResult result =
1147 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1148 EXPECT_TRUE(result.need_unref);
1149 EXPECT_TRUE(result.task);
1151 TestTileTaskRunner::ProcessTask(result.task.get());
1153 DecodedDrawImage decoded_draw_image =
1154 cache.GetDecodedImageForDraw(draw_image);
1155 EXPECT_TRUE(decoded_draw_image.image());
1156 EXPECT_EQ(40, decoded_draw_image.image()->width());
1157 EXPECT_EQ(35, decoded_draw_image.image()->height());
1158 EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
1159 EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
1160 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1161 decoded_draw_image.filter_quality());
1162 EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
1164 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1165 cache.UnrefImage(draw_image);
1168 TEST(SoftwareImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) {
1169 TestSoftwareImageDecodeCache cache;
1170 bool is_decomposable = true;
1171 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
1173 PaintImage paint_image = CreatePaintImage(100, 100);
1174 DrawImage draw_image(
1176 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1177 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1178 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1180 DecodedDrawImage decoded_draw_image =
1181 cache.GetDecodedImageForDraw(draw_image);
1182 EXPECT_TRUE(decoded_draw_image.image());
1183 EXPECT_EQ(50, decoded_draw_image.image()->width());
1184 EXPECT_EQ(50, decoded_draw_image.image()->height());
1185 EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
1186 EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
1187 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1188 decoded_draw_image.filter_quality());
1189 EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
1191 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1194 TEST(SoftwareImageDecodeCacheTest,
1195 GetDecodedImageForDrawAtRasterDecodeMultipleTimes) {
1196 TestSoftwareImageDecodeCache cache;
1197 bool is_decomposable = true;
1198 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
1200 PaintImage paint_image = CreatePaintImage(100, 100);
1201 DrawImage draw_image(
1203 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1204 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1205 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1207 DecodedDrawImage decoded_draw_image =
1208 cache.GetDecodedImageForDraw(draw_image);
1209 ASSERT_TRUE(decoded_draw_image.image());
1210 EXPECT_EQ(50, decoded_draw_image.image()->width());
1211 EXPECT_EQ(50, decoded_draw_image.image()->height());
1212 EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
1213 EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
1214 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1215 decoded_draw_image.filter_quality());
1216 EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
1218 DecodedDrawImage another_decoded_draw_image =
1219 cache.GetDecodedImageForDraw(draw_image);
1220 EXPECT_EQ(decoded_draw_image.image()->uniqueID(),
1221 another_decoded_draw_image.image()->uniqueID());
1223 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1224 cache.DrawWithImageFinished(draw_image, another_decoded_draw_image);
1227 TEST(SoftwareImageDecodeCacheTest, ZeroSizedImagesAreSkipped) {
1228 TestSoftwareImageDecodeCache cache;
1229 bool is_decomposable = true;
1230 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
1232 PaintImage paint_image = CreatePaintImage(100, 100);
1233 DrawImage draw_image(
1235 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1236 CreateMatrix(SkSize::Make(0.f, 0.f), is_decomposable),
1237 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1239 ImageDecodeCache::TaskResult result =
1240 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1241 EXPECT_FALSE(result.task);
1242 EXPECT_FALSE(result.need_unref);
1244 DecodedDrawImage decoded_draw_image =
1245 cache.GetDecodedImageForDraw(draw_image);
1246 EXPECT_FALSE(decoded_draw_image.image());
1248 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1251 TEST(SoftwareImageDecodeCacheTest, NonOverlappingSrcRectImagesAreSkipped) {
1252 TestSoftwareImageDecodeCache cache;
1253 bool is_decomposable = true;
1254 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
1256 PaintImage paint_image = CreatePaintImage(100, 100);
1257 DrawImage draw_image(
1259 SkIRect::MakeXYWH(150, 150, paint_image.width(), paint_image.height()),
1260 quality, CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1261 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1263 ImageDecodeCache::TaskResult result =
1264 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1265 EXPECT_FALSE(result.task);
1266 EXPECT_FALSE(result.need_unref);
1268 DecodedDrawImage decoded_draw_image =
1269 cache.GetDecodedImageForDraw(draw_image);
1270 EXPECT_FALSE(decoded_draw_image.image());
1272 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1275 TEST(SoftwareImageDecodeCacheTest, LowQualityFilterIsHandled) {
1276 TestSoftwareImageDecodeCache cache;
1277 bool is_decomposable = true;
1278 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kLow;
1280 PaintImage paint_image = CreatePaintImage(100, 100);
1281 DrawImage draw_image(
1283 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1284 CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1285 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1287 ImageDecodeCache::TaskResult result =
1288 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1289 EXPECT_TRUE(result.task);
1290 EXPECT_TRUE(result.need_unref);
1292 TestTileTaskRunner::ProcessTask(result.task.get());
1294 DecodedDrawImage decoded_draw_image =
1295 cache.GetDecodedImageForDraw(draw_image);
1296 EXPECT_TRUE(decoded_draw_image.image());
1297 // If we decoded the image and cached it, it would be stored in a different
1299 EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1301 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1302 cache.UnrefImage(draw_image);
1305 TEST(SoftwareImageDecodeCacheTest, LowQualityScaledSubrectIsHandled) {
1306 TestSoftwareImageDecodeCache cache;
1307 bool is_decomposable = true;
1308 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kLow;
1310 PaintImage paint_image = CreatePaintImage(100, 100);
1311 DrawImage draw_image(
1312 paint_image, false, SkIRect::MakeXYWH(10, 10, 80, 80), quality,
1313 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1314 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1316 ImageDecodeCache::TaskResult result =
1317 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1318 EXPECT_TRUE(result.task);
1319 EXPECT_TRUE(result.need_unref);
1321 TestTileTaskRunner::ProcessTask(result.task.get());
1323 DecodedDrawImage decoded_draw_image =
1324 cache.GetDecodedImageForDraw(draw_image);
1325 EXPECT_TRUE(decoded_draw_image.image());
1326 // If we decoded the image and cached it, it would be stored in a different
1328 EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1329 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1330 decoded_draw_image.filter_quality());
1331 // Low quality will be upgraded to medium and mip-mapped.
1332 EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
1333 EXPECT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
1334 EXPECT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
1336 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1337 cache.UnrefImage(draw_image);
1340 TEST(SoftwareImageDecodeCacheTest, NoneQualityScaledSubrectIsHandled) {
1341 TestSoftwareImageDecodeCache cache;
1342 bool is_decomposable = true;
1343 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kNone;
1345 PaintImage paint_image = CreatePaintImage(100, 100);
1346 DrawImage draw_image(
1347 paint_image, false, SkIRect::MakeXYWH(10, 10, 80, 80), quality,
1348 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1349 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1351 ImageDecodeCache::TaskResult result =
1352 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1353 EXPECT_TRUE(result.task);
1354 EXPECT_TRUE(result.need_unref);
1356 TestTileTaskRunner::ProcessTask(result.task.get());
1358 DecodedDrawImage decoded_draw_image =
1359 cache.GetDecodedImageForDraw(draw_image);
1360 EXPECT_TRUE(decoded_draw_image.image());
1361 // If we decoded the image and cached it, it would be stored in a different
1363 EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1364 EXPECT_EQ(PaintFlags::FilterQuality::kNone,
1365 decoded_draw_image.filter_quality());
1366 EXPECT_TRUE(decoded_draw_image.is_scale_adjustment_identity());
1368 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1369 cache.UnrefImage(draw_image);
1372 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt01_5ScaleIsHandled) {
1373 TestSoftwareImageDecodeCache cache;
1374 bool is_decomposable = true;
1375 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
1377 PaintImage paint_image = CreatePaintImage(500, 200);
1378 DrawImage draw_image(
1380 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1381 CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
1382 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1384 ImageDecodeCache::TaskResult result =
1385 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1386 EXPECT_TRUE(result.task);
1387 EXPECT_TRUE(result.need_unref);
1389 TestTileTaskRunner::ProcessTask(result.task.get());
1391 DecodedDrawImage decoded_draw_image =
1392 cache.GetDecodedImageForDraw(draw_image);
1393 EXPECT_TRUE(decoded_draw_image.image());
1394 // Decoded image should not be lazy generated.
1395 EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1396 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1397 decoded_draw_image.filter_quality());
1398 EXPECT_EQ(500, decoded_draw_image.image()->width());
1399 EXPECT_EQ(200, decoded_draw_image.image()->height());
1401 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1402 cache.UnrefImage(draw_image);
1405 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt1_0ScaleIsHandled) {
1406 TestSoftwareImageDecodeCache cache;
1407 bool is_decomposable = true;
1408 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
1410 PaintImage paint_image = CreatePaintImage(500, 200);
1411 DrawImage draw_image(
1413 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1414 CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1415 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1417 ImageDecodeCache::TaskResult result =
1418 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1419 EXPECT_TRUE(result.task);
1420 EXPECT_TRUE(result.need_unref);
1422 TestTileTaskRunner::ProcessTask(result.task.get());
1424 DecodedDrawImage decoded_draw_image =
1425 cache.GetDecodedImageForDraw(draw_image);
1426 EXPECT_TRUE(decoded_draw_image.image());
1427 // Decoded image should not be lazy generated.
1428 EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1429 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1430 decoded_draw_image.filter_quality());
1431 EXPECT_EQ(500, decoded_draw_image.image()->width());
1432 EXPECT_EQ(200, decoded_draw_image.image()->height());
1434 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1435 cache.UnrefImage(draw_image);
1438 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_75ScaleIsHandled) {
1439 TestSoftwareImageDecodeCache cache;
1440 bool is_decomposable = true;
1441 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
1443 PaintImage paint_image = CreatePaintImage(500, 200);
1444 DrawImage draw_image(
1446 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1447 CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
1448 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1450 ImageDecodeCache::TaskResult result =
1451 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1452 EXPECT_TRUE(result.task);
1453 EXPECT_TRUE(result.need_unref);
1455 TestTileTaskRunner::ProcessTask(result.task.get());
1457 DecodedDrawImage decoded_draw_image =
1458 cache.GetDecodedImageForDraw(draw_image);
1459 EXPECT_TRUE(decoded_draw_image.image());
1460 // Decoded image should not be lazy generated.
1461 EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1462 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1463 decoded_draw_image.filter_quality());
1464 EXPECT_EQ(500, decoded_draw_image.image()->width());
1465 EXPECT_EQ(200, decoded_draw_image.image()->height());
1467 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1468 cache.UnrefImage(draw_image);
1471 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_5ScaleIsHandled) {
1472 TestSoftwareImageDecodeCache cache;
1473 bool is_decomposable = true;
1474 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
1476 PaintImage paint_image = CreatePaintImage(500, 200);
1477 DrawImage draw_image(
1479 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1480 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1481 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1483 ImageDecodeCache::TaskResult result =
1484 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1485 EXPECT_TRUE(result.task);
1486 EXPECT_TRUE(result.need_unref);
1488 TestTileTaskRunner::ProcessTask(result.task.get());
1490 DecodedDrawImage decoded_draw_image =
1491 cache.GetDecodedImageForDraw(draw_image);
1492 EXPECT_TRUE(decoded_draw_image.image());
1493 // Decoded image should not be lazy generated.
1494 EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1495 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1496 decoded_draw_image.filter_quality());
1497 EXPECT_EQ(250, decoded_draw_image.image()->width());
1498 EXPECT_EQ(100, decoded_draw_image.image()->height());
1500 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1501 cache.UnrefImage(draw_image);
1504 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_49ScaleIsHandled) {
1505 TestSoftwareImageDecodeCache cache;
1506 bool is_decomposable = true;
1507 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
1509 PaintImage paint_image = CreatePaintImage(500, 200);
1510 DrawImage draw_image(
1512 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1513 CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
1514 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1516 ImageDecodeCache::TaskResult result =
1517 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1518 EXPECT_TRUE(result.task);
1519 EXPECT_TRUE(result.need_unref);
1521 TestTileTaskRunner::ProcessTask(result.task.get());
1523 DecodedDrawImage decoded_draw_image =
1524 cache.GetDecodedImageForDraw(draw_image);
1525 EXPECT_TRUE(decoded_draw_image.image());
1526 // Decoded image should not be lazy generated.
1527 EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1528 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1529 decoded_draw_image.filter_quality());
1530 EXPECT_EQ(250, decoded_draw_image.image()->width());
1531 EXPECT_EQ(100, decoded_draw_image.image()->height());
1533 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1534 cache.UnrefImage(draw_image);
1537 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_1ScaleIsHandled) {
1538 TestSoftwareImageDecodeCache cache;
1539 bool is_decomposable = true;
1540 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
1542 PaintImage paint_image = CreatePaintImage(500, 200);
1543 DrawImage draw_image(
1545 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1546 CreateMatrix(SkSize::Make(0.1f, 0.1f), is_decomposable),
1547 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1549 ImageDecodeCache::TaskResult result =
1550 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1551 EXPECT_TRUE(result.task);
1552 EXPECT_TRUE(result.need_unref);
1554 TestTileTaskRunner::ProcessTask(result.task.get());
1556 DecodedDrawImage decoded_draw_image =
1557 cache.GetDecodedImageForDraw(draw_image);
1558 EXPECT_TRUE(decoded_draw_image.image());
1559 // Decoded image should not be lazy generated.
1560 EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1561 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1562 decoded_draw_image.filter_quality());
1563 EXPECT_EQ(63, decoded_draw_image.image()->width());
1564 EXPECT_EQ(25, decoded_draw_image.image()->height());
1566 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1567 cache.UnrefImage(draw_image);
1570 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_01ScaleIsHandled) {
1571 TestSoftwareImageDecodeCache cache;
1572 bool is_decomposable = true;
1573 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
1575 PaintImage paint_image = CreatePaintImage(500, 200);
1576 DrawImage draw_image(
1578 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1579 CreateMatrix(SkSize::Make(0.01f, 0.01f), is_decomposable),
1580 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1582 ImageDecodeCache::TaskResult result =
1583 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1584 EXPECT_TRUE(result.task);
1585 EXPECT_TRUE(result.need_unref);
1587 TestTileTaskRunner::ProcessTask(result.task.get());
1589 DecodedDrawImage decoded_draw_image =
1590 cache.GetDecodedImageForDraw(draw_image);
1591 EXPECT_TRUE(decoded_draw_image.image());
1592 // Decoded image should not be lazy generated.
1593 EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
1594 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1595 decoded_draw_image.filter_quality());
1596 EXPECT_EQ(8, decoded_draw_image.image()->width());
1597 EXPECT_EQ(4, decoded_draw_image.image()->height());
1599 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1600 cache.UnrefImage(draw_image);
1603 TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_001ScaleIsHandled) {
1604 TestSoftwareImageDecodeCache cache;
1605 bool is_decomposable = true;
1606 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
1608 PaintImage paint_image = CreatePaintImage(500, 200);
1609 DrawImage draw_image(
1611 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1612 CreateMatrix(SkSize::Make(0.001f, 0.001f), is_decomposable),
1613 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1615 ImageDecodeCache::TaskResult result =
1616 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1617 EXPECT_FALSE(result.task);
1618 EXPECT_FALSE(result.need_unref);
1620 DecodedDrawImage decoded_draw_image =
1621 cache.GetDecodedImageForDraw(draw_image);
1622 EXPECT_FALSE(decoded_draw_image.image());
1624 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1627 TEST(SoftwareImageDecodeCacheTest,
1628 MediumQualityImagesAreTheSameAt0_5And0_49Scale) {
1629 TestSoftwareImageDecodeCache cache;
1630 bool is_decomposable = true;
1631 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
1633 PaintImage paint_image = CreatePaintImage(500, 200);
1634 DrawImage draw_image_50(
1636 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1637 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
1638 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1639 DrawImage draw_image_49(
1641 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1642 CreateMatrix(SkSize::Make(0.49f, 0.49f), is_decomposable),
1643 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1645 ImageDecodeCache::TaskResult result_50 = cache.GetTaskForImageAndRef(
1646 draw_image_50, ImageDecodeCache::TracingInfo());
1647 EXPECT_TRUE(result_50.task);
1648 EXPECT_TRUE(result_50.need_unref);
1649 ImageDecodeCache::TaskResult result_49 = cache.GetTaskForImageAndRef(
1650 draw_image_49, ImageDecodeCache::TracingInfo());
1651 EXPECT_TRUE(result_49.task);
1652 EXPECT_TRUE(result_49.need_unref);
1654 TestTileTaskRunner::ProcessTask(result_49.task.get());
1656 DecodedDrawImage decoded_draw_image_50 =
1657 cache.GetDecodedImageForDraw(draw_image_50);
1658 EXPECT_TRUE(decoded_draw_image_50.image());
1659 DecodedDrawImage decoded_draw_image_49 =
1660 cache.GetDecodedImageForDraw(draw_image_49);
1661 EXPECT_TRUE(decoded_draw_image_49.image());
1662 // Decoded image should not be lazy generated.
1663 EXPECT_FALSE(decoded_draw_image_50.image()->isLazyGenerated());
1664 EXPECT_FALSE(decoded_draw_image_49.image()->isLazyGenerated());
1665 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1666 decoded_draw_image_50.filter_quality());
1667 EXPECT_EQ(PaintFlags::FilterQuality::kLow,
1668 decoded_draw_image_49.filter_quality());
1669 EXPECT_EQ(250, decoded_draw_image_50.image()->width());
1670 EXPECT_EQ(250, decoded_draw_image_49.image()->width());
1671 EXPECT_EQ(100, decoded_draw_image_50.image()->height());
1672 EXPECT_EQ(100, decoded_draw_image_49.image()->height());
1674 EXPECT_EQ(decoded_draw_image_50.image(), decoded_draw_image_49.image());
1676 cache.DrawWithImageFinished(draw_image_50, decoded_draw_image_50);
1677 cache.UnrefImage(draw_image_50);
1678 cache.DrawWithImageFinished(draw_image_49, decoded_draw_image_49);
1679 cache.UnrefImage(draw_image_49);
1682 TEST(SoftwareImageDecodeCacheTest, ClearCache) {
1683 TestSoftwareImageDecodeCache cache;
1684 bool is_decomposable = true;
1685 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
1687 for (int i = 0; i < 10; ++i) {
1688 PaintImage paint_image = CreatePaintImage(100, 100);
1689 DrawImage draw_image(
1691 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1692 CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
1693 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1694 ImageDecodeCache::TaskResult result = cache.GetTaskForImageAndRef(
1695 draw_image, ImageDecodeCache::TracingInfo());
1696 EXPECT_TRUE(result.need_unref);
1697 EXPECT_TRUE(result.task);
1698 TestTileTaskRunner::ProcessTask(result.task.get());
1699 cache.UnrefImage(draw_image);
1702 EXPECT_EQ(10u, cache.GetNumCacheEntriesForTesting());
1704 // Tell our cache to clear resources.
1707 EXPECT_EQ(0u, cache.GetNumCacheEntriesForTesting());
1710 TEST(SoftwareImageDecodeCacheTest, CacheDecodesExpectedFrames) {
1711 TestSoftwareImageDecodeCache cache;
1712 std::vector<FrameMetadata> frames = {
1713 FrameMetadata(true, base::Milliseconds(2)),
1714 FrameMetadata(true, base::Milliseconds(3)),
1715 FrameMetadata(true, base::Milliseconds(4)),
1716 FrameMetadata(true, base::Milliseconds(5)),
1718 sk_sp<FakePaintImageGenerator> generator =
1719 sk_make_sp<FakePaintImageGenerator>(
1720 SkImageInfo::MakeN32Premul(10, 10, SkColorSpace::MakeSRGB()), frames);
1721 PaintImage image = PaintImageBuilder::WithDefault()
1722 .set_id(PaintImage::GetNextId())
1723 .set_paint_image_generator(generator)
1726 bool is_decomposable = true;
1727 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
1728 DrawImage draw_image(image, false,
1729 SkIRect::MakeWH(image.width(), image.height()), quality,
1730 CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
1731 1u, DefaultTargetColorParams());
1732 auto decoded_image = cache.GetDecodedImageForDraw(draw_image);
1733 ASSERT_TRUE(decoded_image.image());
1734 ASSERT_EQ(generator->frames_decoded().size(), 1u);
1735 EXPECT_EQ(generator->frames_decoded().count(1u), 1u);
1736 generator->reset_frames_decoded();
1737 cache.DrawWithImageFinished(draw_image, decoded_image);
1740 DrawImage scaled_draw_image(draw_image, 0.5f, 2u,
1741 draw_image.target_color_params());
1742 decoded_image = cache.GetDecodedImageForDraw(scaled_draw_image);
1743 ASSERT_TRUE(decoded_image.image());
1744 ASSERT_EQ(generator->frames_decoded().size(), 1u);
1745 EXPECT_EQ(generator->frames_decoded().count(2u), 1u);
1746 generator->reset_frames_decoded();
1747 cache.DrawWithImageFinished(scaled_draw_image, decoded_image);
1750 DrawImage subset_draw_image(
1751 image, false, SkIRect::MakeWH(5, 5), quality,
1752 CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable), 3u,
1753 DefaultTargetColorParams());
1754 decoded_image = cache.GetDecodedImageForDraw(subset_draw_image);
1755 ASSERT_TRUE(decoded_image.image());
1756 ASSERT_EQ(generator->frames_decoded().size(), 1u);
1757 EXPECT_EQ(generator->frames_decoded().count(3u), 1u);
1758 generator->reset_frames_decoded();
1759 cache.DrawWithImageFinished(subset_draw_image, decoded_image);
1762 TEST(SoftwareImageDecodeCacheTest, SizeSubrectingIsHandled) {
1763 const int min_dimension = 4 * 1024 + 2;
1764 TestSoftwareImageDecodeCache cache;
1765 bool is_decomposable = true;
1766 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kLow;
1768 auto paint_image = CreateDiscardablePaintImage(
1769 gfx::Size(min_dimension, min_dimension), DefaultSkColorSpace(), false);
1770 DrawImage draw_image(
1771 paint_image, false, SkIRect::MakeXYWH(0, 0, 10, 10), quality,
1772 CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1773 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1775 ImageDecodeCache::TaskResult result =
1776 cache.GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
1777 EXPECT_TRUE(result.task);
1778 EXPECT_TRUE(result.need_unref);
1780 TestTileTaskRunner::ProcessTask(result.task.get());
1782 DecodedDrawImage decoded_draw_image =
1783 cache.GetDecodedImageForDraw(draw_image);
1784 // Since we didn't allocate any backing for the memory, we expect this to be
1785 // false. This test is here to ensure that we at least got to the point where
1786 // we tried to decode something instead of recursing infinitely.
1787 EXPECT_FALSE(decoded_draw_image.image());
1788 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1789 cache.UnrefImage(draw_image);
1792 TEST(SoftwareImageDecodeCacheTest, EmptyTargetSizeDecode) {
1793 // Tests that requesting an empty sized decode followed by an original sized
1794 // decode returns no decoded images. This is a regression test. See
1795 // crbug.com/802976.
1797 TestSoftwareImageDecodeCache cache;
1798 bool is_decomposable = true;
1799 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kLow;
1801 // Populate the cache with an original sized decode.
1803 CreateDiscardablePaintImage(gfx::Size(100, 100), DefaultSkColorSpace());
1804 DrawImage draw_image(paint_image, false, SkIRect::MakeWH(100, 100), quality,
1805 CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1806 PaintImage::kDefaultFrameIndex,
1807 DefaultTargetColorParams());
1808 DecodedDrawImage decoded_draw_image =
1809 cache.GetDecodedImageForDraw(draw_image);
1810 EXPECT_TRUE(decoded_draw_image.image());
1811 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1813 // Ask for another decode, this time with an empty subrect.
1814 DrawImage empty_draw_image(
1815 paint_image, false, SkIRect::MakeEmpty(), quality,
1816 CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1817 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1818 DecodedDrawImage empty_decoded_draw_image =
1819 cache.GetDecodedImageForDraw(empty_draw_image);
1820 EXPECT_FALSE(empty_decoded_draw_image.image());
1821 cache.DrawWithImageFinished(empty_draw_image, empty_decoded_draw_image);
1824 TEST(SoftwareImageDecodeCacheTest, BitmapImageColorConverted) {
1825 TestSoftwareImageDecodeCache cache;
1826 bool is_decomposable = true;
1827 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
1828 const TargetColorParams target_color_params(
1829 gfx::ColorSpace::CreateDisplayP3D65());
1831 PaintImage paint_image = CreateBitmapImage(gfx::Size(100, 100));
1832 DrawImage draw_image(
1834 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1835 CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1836 PaintImage::kDefaultFrameIndex, target_color_params);
1838 DecodedDrawImage decoded_draw_image =
1839 cache.GetDecodedImageForDraw(draw_image);
1840 EXPECT_TRUE(decoded_draw_image.image());
1841 // Expect that we allocated a new image.
1842 EXPECT_NE(decoded_draw_image.image().get(), paint_image.GetSwSkImage().get());
1843 // Expect that the image color space match the target color space.
1844 EXPECT_TRUE(decoded_draw_image.image()->colorSpace());
1845 EXPECT_TRUE(SkColorSpace::Equals(
1846 decoded_draw_image.image()->colorSpace(),
1847 target_color_params.color_space.ToSkColorSpace().get()));
1849 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1852 TEST(SoftwareImageDecodeCacheTest, BitmapImageNotColorConverted) {
1853 TestSoftwareImageDecodeCache cache;
1854 bool is_decomposable = true;
1855 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
1857 PaintImage paint_image = CreateBitmapImage(gfx::Size(100, 100));
1858 DrawImage draw_image(
1860 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1861 CreateMatrix(SkSize::Make(1.f, 1.f), is_decomposable),
1862 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1864 // The cache should not support this image.
1865 EXPECT_FALSE(cache.UseCacheForDrawImage(draw_image));
1868 // TODO(ccameron): Re-enable this when the root cause of crashes is discovered.
1869 // https://crbug.com/791828
1870 TEST(SoftwareImageDecodeCacheTest, DISABLED_ContentIdCaching) {
1871 TestSoftwareImageDecodeCache cache;
1872 bool is_decomposable = true;
1873 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
1874 PaintImage::Id stable_id = 1001;
1876 for (int i = 0; i < 10; ++i) {
1877 // Create several images with the same stable id, but new content ids.
1878 PaintImage paint_image = CreateDiscardablePaintImage(
1879 gfx::Size(100, 100), nullptr, true, stable_id);
1881 // Cache two entries of different scales.
1882 for (int j = 0; j < 2; ++j) {
1883 float scale = j == 0 ? 1.f : 0.5f;
1884 DrawImage draw_image(
1886 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1887 CreateMatrix(SkSize::Make(scale, scale), is_decomposable),
1888 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1889 DecodedDrawImage decoded_draw_image =
1890 cache.GetDecodedImageForDraw(draw_image);
1891 EXPECT_TRUE(decoded_draw_image.image());
1892 cache.DrawWithImageFinished(draw_image, decoded_draw_image);
1895 // After the first two entries come in, we start evicting old content ids.
1897 EXPECT_LE(cache.GetNumCacheEntriesForTesting(), 2u);
1899 EXPECT_LE(cache.GetNumCacheEntriesForTesting(), 4u);
1903 TEST(SoftwareImageDecodeCacheTest, DecodeToScale) {
1904 TestSoftwareImageDecodeCache cache;
1905 bool is_decomposable = true;
1906 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
1908 SkISize full_size = SkISize::Make(100, 100);
1909 std::vector<SkISize> supported_sizes = {SkISize::Make(25, 25),
1910 SkISize::Make(50, 50)};
1911 std::vector<FrameMetadata> frames = {FrameMetadata()};
1912 sk_sp<FakePaintImageGenerator> generator =
1913 sk_make_sp<FakePaintImageGenerator>(
1914 SkImageInfo::MakeN32Premul(full_size.width(), full_size.height(),
1915 DefaultSkColorSpace()),
1916 frames, true, supported_sizes);
1917 PaintImage paint_image = PaintImageBuilder::WithDefault()
1918 .set_id(PaintImage::GetNextId())
1919 .set_paint_image_generator(generator)
1922 // Scale to mip level 1, there should be a single entry in the cache from
1923 // the direct decode.
1924 DrawImage draw_image1(
1926 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1927 CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
1928 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1929 DecodedDrawImage decoded_image1 = cache.GetDecodedImageForDraw(draw_image1);
1930 ASSERT_TRUE(decoded_image1.image());
1931 EXPECT_EQ(decoded_image1.image()->width(), 50);
1932 EXPECT_EQ(decoded_image1.image()->height(), 50);
1933 EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 1u);
1935 // We should have requested a scaled decode from the generator.
1936 ASSERT_EQ(generator->decode_infos().size(), 1u);
1937 EXPECT_EQ(generator->decode_infos().at(0).width(), 50);
1938 EXPECT_EQ(generator->decode_infos().at(0).height(), 50);
1940 // Scale to mip level 2, we should be using the existing entry instead of
1942 DrawImage draw_image2(
1944 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
1945 CreateMatrix(SkSize::Make(0.25, 0.25), is_decomposable),
1946 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
1947 DecodedDrawImage decoded_image2 = cache.GetDecodedImageForDraw(draw_image2);
1948 ASSERT_TRUE(decoded_image2.image());
1949 EXPECT_EQ(decoded_image2.image()->width(), 25);
1950 EXPECT_EQ(decoded_image2.image()->height(), 25);
1951 EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 2u);
1953 // Since we scaled from the existing entry, no new decodes should be
1954 // requested from the generator.
1955 ASSERT_EQ(generator->decode_infos().size(), 1u);
1956 EXPECT_EQ(generator->decode_infos().at(0).width(), 50);
1957 EXPECT_EQ(generator->decode_infos().at(0).height(), 50);
1959 cache.DrawWithImageFinished(draw_image1, decoded_image1);
1960 cache.DrawWithImageFinished(draw_image2, decoded_image2);
1963 TEST(SoftwareImageDecodeCacheTest, DecodeToScaleSubrect) {
1964 TestSoftwareImageDecodeCache cache;
1965 bool is_decomposable = true;
1966 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
1968 SkISize full_size = SkISize::Make(100, 100);
1969 std::vector<SkISize> supported_sizes = {SkISize::Make(25, 25),
1970 SkISize::Make(50, 50)};
1971 std::vector<FrameMetadata> frames = {FrameMetadata()};
1972 sk_sp<FakePaintImageGenerator> generator =
1973 sk_make_sp<FakePaintImageGenerator>(
1974 SkImageInfo::MakeN32Premul(full_size.width(), full_size.height(),
1975 DefaultSkColorSpace()),
1976 frames, true, supported_sizes);
1977 PaintImage paint_image = PaintImageBuilder::WithDefault()
1978 .set_id(PaintImage::GetNextId())
1979 .set_paint_image_generator(generator)
1982 // Scale to mip level 1, there should be 2 entries in the cache, since the
1983 // subrect vetoes decode to scale.
1984 DrawImage draw_image(paint_image, false, SkIRect::MakeWH(50, 50), quality,
1985 CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
1986 PaintImage::kDefaultFrameIndex,
1987 DefaultTargetColorParams());
1988 DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
1989 ASSERT_TRUE(decoded_image.image());
1990 EXPECT_EQ(decoded_image.image()->width(), 25);
1991 EXPECT_EQ(decoded_image.image()->height(), 25);
1992 EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 2u);
1994 // We should have requested the original decode from the generator.
1995 ASSERT_EQ(generator->decode_infos().size(), 1u);
1996 EXPECT_EQ(generator->decode_infos().at(0).width(), 100);
1997 EXPECT_EQ(generator->decode_infos().at(0).height(), 100);
1998 cache.DrawWithImageFinished(draw_image, decoded_image);
2001 TEST(SoftwareImageDecodeCacheTest, DecodeToScaleNoneQuality) {
2002 TestSoftwareImageDecodeCache cache;
2003 bool is_decomposable = true;
2004 PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kNone;
2006 SkISize full_size = SkISize::Make(100, 100);
2007 std::vector<SkISize> supported_sizes = {SkISize::Make(25, 25),
2008 SkISize::Make(50, 50)};
2009 std::vector<FrameMetadata> frames = {FrameMetadata()};
2010 sk_sp<FakePaintImageGenerator> generator =
2011 sk_make_sp<FakePaintImageGenerator>(
2012 SkImageInfo::MakeN32Premul(full_size.width(), full_size.height(),
2013 DefaultSkColorSpace()),
2014 frames, true, supported_sizes);
2015 PaintImage paint_image = PaintImageBuilder::WithDefault()
2016 .set_id(PaintImage::GetNextId())
2017 .set_paint_image_generator(generator)
2020 DrawImage draw_image(
2022 SkIRect::MakeWH(paint_image.width(), paint_image.height()), quality,
2023 CreateMatrix(SkSize::Make(0.5, 0.5), is_decomposable),
2024 PaintImage::kDefaultFrameIndex, DefaultTargetColorParams());
2025 DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
2026 ASSERT_TRUE(decoded_image.image());
2027 EXPECT_EQ(decoded_image.image()->width(), 100);
2028 EXPECT_EQ(decoded_image.image()->height(), 100);
2030 // We should have requested the original decode from the generator.
2031 ASSERT_EQ(generator->decode_infos().size(), 1u);
2032 EXPECT_EQ(generator->decode_infos().at(0).width(), 100);
2033 EXPECT_EQ(generator->decode_infos().at(0).height(), 100);
2034 cache.DrawWithImageFinished(draw_image, decoded_image);
2037 TEST(SoftwareImageDecodeCacheTest, HdrDecodeToHdr) {
2038 TestSoftwareImageDecodeCache cache;
2040 const TargetColorParams target_color_params(gfx::ColorSpace::CreateHDR10());
2041 auto size = SkISize::Make(100, 100);
2042 auto info = SkImageInfo::Make(
2043 size.width(), size.height(), kRGBA_F16_SkColorType, kPremul_SkAlphaType,
2044 target_color_params.color_space.ToSkColorSpace());
2046 bitmap.allocPixels(info);
2047 PaintImage image = PaintImageBuilder::WithDefault()
2048 .set_id(PaintImage::kInvalidId)
2049 .set_is_high_bit_depth(true)
2050 .set_image(SkImage::MakeFromBitmap(bitmap),
2051 PaintImage::GetNextContentId())
2054 DrawImage draw_image(image, false,
2055 SkIRect::MakeWH(image.width(), image.height()),
2056 PaintFlags::FilterQuality::kMedium,
2057 CreateMatrix(SkSize::Make(0.5, 0.5), true),
2058 PaintImage::kDefaultFrameIndex, target_color_params);
2060 DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
2061 EXPECT_EQ(decoded_image.image()->colorType(), kRGBA_F16_SkColorType);
2062 cache.DrawWithImageFinished(draw_image, decoded_image);
2065 TEST(SoftwareImageDecodeCacheTest, HdrDecodeToSdr) {
2066 TestSoftwareImageDecodeCache cache;
2068 auto image_color_space = gfx::ColorSpace::CreateHDR10();
2069 auto size = SkISize::Make(100, 100);
2070 auto info = SkImageInfo::Make(size.width(), size.height(),
2071 kRGBA_F16_SkColorType, kPremul_SkAlphaType,
2072 image_color_space.ToSkColorSpace());
2074 bitmap.allocPixels(info);
2075 PaintImage image = PaintImageBuilder::WithDefault()
2076 .set_id(PaintImage::kInvalidId)
2077 .set_is_high_bit_depth(true)
2078 .set_image(SkImage::MakeFromBitmap(bitmap),
2079 PaintImage::GetNextContentId())
2082 // Note: We use P3 here since software cache shouldn't be used when conversion
2083 // to SRGB is needed.
2084 auto raster_color_space = gfx::ColorSpace::CreateDisplayP3D65();
2085 DrawImage draw_image(
2086 image, false, SkIRect::MakeWH(image.width(), image.height()),
2087 PaintFlags::FilterQuality::kMedium,
2088 CreateMatrix(SkSize::Make(0.5, 0.5), true),
2089 PaintImage::kDefaultFrameIndex, TargetColorParams(raster_color_space));
2091 DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
2092 EXPECT_NE(decoded_image.image()->colorType(), kRGBA_F16_SkColorType);
2093 cache.DrawWithImageFinished(draw_image, decoded_image);