Home | History | Annotate | Download | only in tests
      1 /*
      2 * Copyright 2014 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 #if SK_SUPPORT_GPU
      9 
     10 #include "GrContext.h"
     11 #include "GrContextFactory.h"
     12 #include "GrLayerCache.h"
     13 #include "SkPictureRecorder.h"
     14 #include "Test.h"
     15 
     16 class TestingAccess {
     17 public:
     18     static int NumLayers(GrLayerCache* cache) {
     19         return cache->numLayers();
     20     }
     21     static void Purge(GrLayerCache* cache, uint32_t pictureID) {
     22         cache->purge(pictureID);
     23     }
     24 };
     25 
     26 // Add several layers to the cache
     27 static void create_layers(skiatest::Reporter* reporter,
     28                           GrLayerCache* cache,
     29                           const SkPicture& picture,
     30                           int numToAdd,
     31                           int idOffset) {
     32 
     33     for (int i = 0; i < numToAdd; ++i) {
     34         GrCachedLayer* layer = cache->findLayerOrCreate(picture.uniqueID(),
     35                                                         idOffset+i+1, idOffset+i+2,
     36                                                         SkIPoint::Make(0, 0),
     37                                                         SkMatrix::I(),
     38                                                         NULL);
     39         REPORTER_ASSERT(reporter, layer);
     40         GrCachedLayer* temp = cache->findLayer(picture.uniqueID(), idOffset+i+1, idOffset+i+2,
     41                                                SkIPoint::Make(0, 0), SkMatrix::I());
     42         REPORTER_ASSERT(reporter, temp == layer);
     43 
     44         REPORTER_ASSERT(reporter, TestingAccess::NumLayers(cache) == idOffset + i + 1);
     45 
     46         REPORTER_ASSERT(reporter, picture.uniqueID() == layer->pictureID());
     47         REPORTER_ASSERT(reporter, layer->start() == idOffset + i + 1);
     48         REPORTER_ASSERT(reporter, layer->stop() == idOffset + i + 2);
     49         REPORTER_ASSERT(reporter, layer->ctm() == SkMatrix::I());
     50         REPORTER_ASSERT(reporter, NULL == layer->texture());
     51         REPORTER_ASSERT(reporter, NULL == layer->paint());
     52         REPORTER_ASSERT(reporter, !layer->isAtlased());
     53     }
     54 
     55     cache->trackPicture(&picture);
     56 }
     57 
     58 static void lock_layer(skiatest::Reporter* reporter,
     59                        GrLayerCache* cache,
     60                        GrCachedLayer* layer) {
     61     // Make the layer 512x512 (so it can be atlased)
     62     GrTextureDesc desc;
     63     desc.fWidth = 512;
     64     desc.fHeight = 512;
     65     desc.fConfig = kSkia8888_GrPixelConfig;
     66 
     67     bool needsRerendering = cache->lock(layer, desc, false);
     68     REPORTER_ASSERT(reporter, needsRerendering);
     69 
     70     needsRerendering = cache->lock(layer, desc, false);
     71     REPORTER_ASSERT(reporter, !needsRerendering);
     72 
     73     REPORTER_ASSERT(reporter, layer->texture());
     74     REPORTER_ASSERT(reporter, layer->locked());
     75 }
     76 
     77 // This test case exercises the public API of the GrLayerCache class.
     78 // In particular it checks its interaction with the resource cache (w.r.t.
     79 // locking & unlocking textures).
     80 // TODO: need to add checks on VRAM usage!
     81 DEF_GPUTEST(GpuLayerCache, reporter, factory) {
     82     static const int kInitialNumLayers = 5;
     83 
     84     for (int i= 0; i < GrContextFactory::kGLContextTypeCnt; ++i) {
     85         GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
     86 
     87         if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
     88             continue;
     89         }
     90 
     91         GrContext* context = factory->get(glCtxType);
     92 
     93         if (NULL == context) {
     94             continue;
     95         }
     96 
     97         SkPictureRecorder recorder;
     98         recorder.beginRecording(1, 1);
     99         SkAutoTUnref<const SkPicture> picture(recorder.endRecording());
    100 
    101         GrLayerCache cache(context);
    102 
    103         create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
    104 
    105         for (int i = 0; i < kInitialNumLayers; ++i) {
    106             GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2,
    107                                                    SkIPoint::Make(0, 0), SkMatrix::I());
    108             REPORTER_ASSERT(reporter, layer);
    109 
    110             lock_layer(reporter, &cache, layer);
    111 
    112             // The first 4 layers should be in the atlas (and thus have non-empty
    113             // rects)
    114             if (i < 4) {
    115                 REPORTER_ASSERT(reporter, layer->isAtlased());
    116             } else {
    117                 // The 5th layer couldn't fit in the atlas
    118                 REPORTER_ASSERT(reporter, !layer->isAtlased());
    119             }
    120         }
    121 
    122         // Unlock the textures
    123         for (int i = 0; i < kInitialNumLayers; ++i) {
    124             GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2,
    125                                                    SkIPoint::Make(0, 0), SkMatrix::I());
    126             REPORTER_ASSERT(reporter, layer);
    127             cache.unlock(layer);
    128         }
    129 
    130         for (int i = 0; i < kInitialNumLayers; ++i) {
    131             GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2,
    132                                                    SkIPoint::Make(0, 0), SkMatrix::I());
    133             REPORTER_ASSERT(reporter, layer);
    134 
    135             REPORTER_ASSERT(reporter, !layer->locked());
    136             // The first 4 layers should still be in the atlas.
    137             if (i < 4) {
    138                 REPORTER_ASSERT(reporter, layer->texture());
    139                 REPORTER_ASSERT(reporter, layer->isAtlased());
    140             } else {
    141                 // The final layer should be unlocked.
    142                 REPORTER_ASSERT(reporter, NULL == layer->texture());
    143                 REPORTER_ASSERT(reporter, !layer->isAtlased());
    144             }
    145         }
    146 
    147         {
    148             // Add an additional layer. Since all the layers are unlocked this
    149             // will force out the first atlased layer
    150             create_layers(reporter, &cache, *picture, 1, kInitialNumLayers);
    151             GrCachedLayer* layer = cache.findLayer(picture->uniqueID(),
    152                                                    kInitialNumLayers+1, kInitialNumLayers+2,
    153                                                    SkIPoint::Make(0, 0), SkMatrix::I());
    154             REPORTER_ASSERT(reporter, layer);
    155 
    156             lock_layer(reporter, &cache, layer);
    157             cache.unlock(layer);
    158         }
    159 
    160         for (int i = 0; i < kInitialNumLayers+1; ++i) {
    161             GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2,
    162                                                    SkIPoint::Make(0, 0), SkMatrix::I());
    163             // 3 old layers plus the new one should be in the atlas.
    164             if (1 == i || 2 == i || 3 == i || 5 == i) {
    165                 REPORTER_ASSERT(reporter, layer);
    166                 REPORTER_ASSERT(reporter, !layer->locked());
    167                 REPORTER_ASSERT(reporter, layer->texture());
    168                 REPORTER_ASSERT(reporter, layer->isAtlased());
    169             } else if (4 == i) {
    170                 // The one that was never atlased should still be around
    171                 REPORTER_ASSERT(reporter, layer);
    172 
    173                 REPORTER_ASSERT(reporter, NULL == layer->texture());
    174                 REPORTER_ASSERT(reporter, !layer->isAtlased());
    175             } else {
    176                 // The one bumped out of the atlas (i.e., 0) should be gone
    177                 REPORTER_ASSERT(reporter, NULL == layer);
    178             }
    179         }
    180 
    181         //--------------------------------------------------------------------
    182         // Free them all SkGpuDevice-style. This will not free up the
    183         // atlas' texture but will eliminate all the layers.
    184         TestingAccess::Purge(&cache, picture->uniqueID());
    185 
    186         REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
    187         // TODO: add VRAM/resource cache check here
    188 
    189         //--------------------------------------------------------------------
    190         // Test out the GrContext-style purge. This should remove all the layers
    191         // and the atlas.
    192         // Re-create the layers
    193         create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
    194 
    195         // Free them again GrContext-style. This should free up everything.
    196         cache.freeAll();
    197 
    198         REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
    199         // TODO: add VRAM/resource cache check here
    200 
    201         //--------------------------------------------------------------------
    202         // Test out the MessageBus-style purge. This will not free the atlas
    203         // but should eliminate the free-floating layers.
    204         create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
    205 
    206         picture.reset(NULL);
    207         cache.processDeletedPictures();
    208 
    209         REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
    210         // TODO: add VRAM/resource cache check here
    211     }
    212 }
    213 
    214 #endif
    215