Home | History | Annotate | Download | only in tests
      1  /*
      2   * Copyright 2016 Google Inc.
      3   *
      4   * Use of this source code is governed by a BSD-style license that can be
      5   * found in the LICENSE file.
      6   */
      7 
      8 #include "Test.h"
      9 
     10 #include "SkBitmap.h"
     11 #include "SkImage.h"
     12 #include "SkImageFilter.h"
     13 #include "SkImageFilterCacheKey.h"
     14 #include "SkMatrix.h"
     15 #include "SkSpecialImage.h"
     16 
     17 static const int kSmallerSize = 10;
     18 static const int kPad = 3;
     19 static const int kFullSize = kSmallerSize + 2 * kPad;
     20 
     21 static SkBitmap create_bm() {
     22     SkBitmap bm;
     23     bm.allocN32Pixels(kFullSize, kFullSize, true);
     24     bm.eraseColor(SK_ColorTRANSPARENT);
     25     return bm;
     26 }
     27 
     28 // Ensure the cache can return a cached image
     29 static void test_find_existing(skiatest::Reporter* reporter,
     30                                SkSpecialImage* image,
     31                                SkSpecialImage* subset) {
     32     static const size_t kCacheSize = 1000000;
     33     SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(kCacheSize));
     34 
     35     SkIRect clip = SkIRect::MakeWH(100, 100);
     36     SkImageFilter::Cache::Key key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
     37     SkImageFilter::Cache::Key key2(0, SkMatrix::I(), clip, subset->uniqueID(), subset->subset());
     38 
     39     SkIPoint offset = SkIPoint::Make(3, 4);
     40     cache->set(key1, image, offset);
     41 
     42     SkIPoint foundOffset;
     43 
     44     SkSpecialImage* foundImage = cache->get(key1, &foundOffset);
     45     REPORTER_ASSERT(reporter, foundImage);
     46     REPORTER_ASSERT(reporter, offset == foundOffset);
     47 
     48     REPORTER_ASSERT(reporter, !cache->get(key2, &foundOffset));
     49 }
     50 
     51 // If either id is different or the clip or the matrix are different the
     52 // cached image won't be found. Even if it is caching the same bitmap.
     53 static void test_dont_find_if_diff_key(skiatest::Reporter* reporter,
     54                                        SkSpecialImage* image,
     55                                        SkSpecialImage* subset) {
     56     static const size_t kCacheSize = 1000000;
     57     SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(kCacheSize));
     58 
     59     SkIRect clip1 = SkIRect::MakeWH(100, 100);
     60     SkIRect clip2 = SkIRect::MakeWH(200, 200);
     61     SkImageFilter::Cache::Key key0(0, SkMatrix::I(), clip1, image->uniqueID(), image->subset());
     62     SkImageFilter::Cache::Key key1(1, SkMatrix::I(), clip1, image->uniqueID(), image->subset());
     63     SkImageFilter::Cache::Key key2(0, SkMatrix::MakeTrans(5, 5), clip1,
     64                                    image->uniqueID(), image->subset());
     65     SkImageFilter::Cache::Key key3(0, SkMatrix::I(), clip2, image->uniqueID(), image->subset());
     66     SkImageFilter::Cache::Key key4(0, SkMatrix::I(), clip1, subset->uniqueID(), subset->subset());
     67 
     68     SkIPoint offset = SkIPoint::Make(3, 4);
     69     cache->set(key0, image, offset);
     70 
     71     SkIPoint foundOffset;
     72     REPORTER_ASSERT(reporter, !cache->get(key1, &foundOffset));
     73     REPORTER_ASSERT(reporter, !cache->get(key2, &foundOffset));
     74     REPORTER_ASSERT(reporter, !cache->get(key3, &foundOffset));
     75     REPORTER_ASSERT(reporter, !cache->get(key4, &foundOffset));
     76 }
     77 
     78 // Test purging when the max cache size is exceeded
     79 static void test_internal_purge(skiatest::Reporter* reporter, SkSpecialImage* image) {
     80     SkASSERT(image->getSize());
     81     const size_t kCacheSize = image->getSize() + 10;
     82     SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(kCacheSize));
     83 
     84     SkIRect clip = SkIRect::MakeWH(100, 100);
     85     SkImageFilter::Cache::Key key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
     86     SkImageFilter::Cache::Key key2(1, SkMatrix::I(), clip, image->uniqueID(), image->subset());
     87 
     88     SkIPoint offset = SkIPoint::Make(3, 4);
     89     cache->set(key1, image, offset);
     90 
     91     SkIPoint foundOffset;
     92 
     93     REPORTER_ASSERT(reporter, cache->get(key1, &foundOffset));
     94 
     95     // This should knock the first one out of the cache
     96     cache->set(key2, image, offset);
     97 
     98     REPORTER_ASSERT(reporter, cache->get(key2, &foundOffset));
     99     REPORTER_ASSERT(reporter, !cache->get(key1, &foundOffset));
    100 }
    101 
    102 // Exercise the purgeByKeys and purge methods
    103 static void test_explicit_purging(skiatest::Reporter* reporter,
    104                                   SkSpecialImage* image,
    105                                   SkSpecialImage* subset) {
    106     static const size_t kCacheSize = 1000000;
    107     SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(kCacheSize));
    108 
    109     SkIRect clip = SkIRect::MakeWH(100, 100);
    110     SkImageFilter::Cache::Key key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
    111     SkImageFilter::Cache::Key key2(1, SkMatrix::I(), clip, subset->uniqueID(), image->subset());
    112 
    113     SkIPoint offset = SkIPoint::Make(3, 4);
    114     cache->set(key1, image, offset);
    115     cache->set(key2, image, offset);
    116 
    117     SkIPoint foundOffset;
    118 
    119     REPORTER_ASSERT(reporter, cache->get(key1, &foundOffset));
    120     REPORTER_ASSERT(reporter, cache->get(key2, &foundOffset));
    121 
    122     cache->purgeByKeys(&key1, 1);
    123 
    124     REPORTER_ASSERT(reporter, !cache->get(key1, &foundOffset));
    125     REPORTER_ASSERT(reporter, cache->get(key2, &foundOffset));
    126 
    127     cache->purge();
    128 
    129     REPORTER_ASSERT(reporter, !cache->get(key1, &foundOffset));
    130     REPORTER_ASSERT(reporter, !cache->get(key2, &foundOffset));
    131 }
    132 
    133 DEF_TEST(ImageFilterCache_RasterBacked, reporter) {
    134     SkBitmap srcBM = create_bm();
    135 
    136     const SkIRect& full = SkIRect::MakeWH(kFullSize, kFullSize);
    137 
    138     SkAutoTUnref<SkSpecialImage> fullImg(SkSpecialImage::NewFromRaster(nullptr, full, srcBM));
    139 
    140     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
    141 
    142     SkAutoTUnref<SkSpecialImage> subsetImg(SkSpecialImage::NewFromRaster(nullptr, subset, srcBM));
    143 
    144     test_find_existing(reporter, fullImg, subsetImg);
    145     test_dont_find_if_diff_key(reporter, fullImg, subsetImg);
    146     test_internal_purge(reporter, fullImg);
    147     test_explicit_purging(reporter, fullImg, subsetImg);
    148 }
    149 
    150 
    151 // Shared test code for both the raster and gpu-backed image cases
    152 static void test_image_backed(skiatest::Reporter* reporter, SkImage* srcImage) {
    153     const SkIRect& full = SkIRect::MakeWH(kFullSize, kFullSize);
    154 
    155     SkAutoTUnref<SkSpecialImage> fullImg(SkSpecialImage::NewFromImage(full, srcImage));
    156 
    157     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
    158 
    159     SkAutoTUnref<SkSpecialImage> subsetImg(SkSpecialImage::NewFromImage(subset, srcImage));
    160 
    161     test_find_existing(reporter, fullImg, subsetImg);
    162     test_dont_find_if_diff_key(reporter, fullImg, subsetImg);
    163     test_internal_purge(reporter, fullImg);
    164     test_explicit_purging(reporter, fullImg, subsetImg);
    165 }
    166 
    167 DEF_TEST(ImageFilterCache_ImageBackedRaster, reporter) {
    168     SkBitmap srcBM = create_bm();
    169 
    170     SkAutoTUnref<SkImage> srcImage(SkImage::NewFromBitmap(srcBM));
    171 
    172     test_image_backed(reporter, srcImage);
    173 }
    174 
    175 #if SK_SUPPORT_GPU
    176 #include "GrContext.h"
    177 
    178 static GrTexture* create_texture(GrContext* context) {
    179     SkBitmap srcBM = create_bm();
    180 
    181     GrSurfaceDesc desc;
    182     desc.fConfig = kSkia8888_GrPixelConfig;
    183     desc.fFlags  = kNone_GrSurfaceFlags;
    184     desc.fWidth  = kFullSize;
    185     desc.fHeight = kFullSize;
    186 
    187     return context->textureProvider()->createTexture(desc, SkBudgeted::kNo, srcBM.getPixels(), 0);
    188 }
    189 
    190 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterCache_ImageBackedGPU, reporter, context) {
    191     SkAutoTUnref<GrTexture> srcTexture(create_texture(context));
    192     if (!srcTexture) {
    193         return;
    194     }
    195 
    196     GrBackendTextureDesc backendDesc;
    197     backendDesc.fConfig = kSkia8888_GrPixelConfig;
    198     backendDesc.fFlags = kNone_GrBackendTextureFlag;
    199     backendDesc.fWidth = kFullSize;
    200     backendDesc.fHeight = kFullSize;
    201     backendDesc.fSampleCnt = 0;
    202     backendDesc.fTextureHandle = srcTexture->getTextureHandle();
    203     SkAutoTUnref<SkImage> srcImage(SkImage::NewFromTexture(context, backendDesc,
    204                                                            kPremul_SkAlphaType));
    205     if (!srcImage) {
    206         return;
    207     }
    208 
    209     test_image_backed(reporter, srcImage);
    210 }
    211 
    212 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterCache_GPUBacked, reporter, context) {
    213 
    214     SkAutoTUnref<GrTexture> srcTexture(create_texture(context));
    215     if (!srcTexture) {
    216         return;
    217     }
    218 
    219     const SkIRect& full = SkIRect::MakeWH(kFullSize, kFullSize);
    220 
    221     SkAutoTUnref<SkSpecialImage> fullImg(SkSpecialImage::NewFromGpu(
    222                                                                 nullptr, full,
    223                                                                 kNeedNewImageUniqueID_SpecialImage,
    224                                                                 srcTexture));
    225 
    226     const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
    227 
    228     SkAutoTUnref<SkSpecialImage> subsetImg(SkSpecialImage::NewFromGpu(
    229                                                                 nullptr, subset,
    230                                                                 kNeedNewImageUniqueID_SpecialImage,
    231                                                                 srcTexture));
    232 
    233     test_find_existing(reporter, fullImg, subsetImg);
    234     test_dont_find_if_diff_key(reporter, fullImg, subsetImg);
    235     test_internal_purge(reporter, fullImg);
    236     test_explicit_purging(reporter, fullImg, subsetImg);
    237 }
    238 #endif
    239 
    240