Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2012 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 
      9 #include "Test.h"
     10 // This is a GR test
     11 #if SK_SUPPORT_GPU
     12 #include "GrContextFactory.h"
     13 #include "SkGpuDevice.h"
     14 #include "../../src/gpu/GrClipMaskManager.h"
     15 
     16 static const int X_SIZE = 12;
     17 static const int Y_SIZE = 12;
     18 
     19 ////////////////////////////////////////////////////////////////////////////////
     20 // note: this is unused
     21 static GrTexture* createTexture(GrContext* context) {
     22     unsigned char textureData[X_SIZE][Y_SIZE][4];
     23 
     24     memset(textureData, 0, 4* X_SIZE * Y_SIZE);
     25 
     26     GrTextureDesc desc;
     27 
     28     // let Skia know we will be using this texture as a render target
     29     desc.fFlags     = kRenderTarget_GrTextureFlagBit;
     30     desc.fConfig    = kSkia8888_GrPixelConfig;
     31     desc.fWidth     = X_SIZE;
     32     desc.fHeight    = Y_SIZE;
     33 
     34     // We are initializing the texture with zeros here
     35     GrTexture* texture = context->createUncachedTexture(desc, textureData, 0);
     36     if (!texture) {
     37         return NULL;
     38     }
     39 
     40     return texture;
     41 }
     42 
     43 // Ensure that the 'getConservativeBounds' calls are returning bounds clamped
     44 // to the render target
     45 static void test_clip_bounds(skiatest::Reporter* reporter, GrContext* context) {
     46 
     47     static const int kXSize = 100;
     48     static const int kYSize = 100;
     49 
     50     GrTextureDesc desc;
     51     desc.fFlags     = kRenderTarget_GrTextureFlagBit;
     52     desc.fConfig    = kAlpha_8_GrPixelConfig;
     53     desc.fWidth     = kXSize;
     54     desc.fHeight    = kYSize;
     55 
     56     GrTexture* texture = context->createUncachedTexture(desc, NULL, 0);
     57     if (!texture) {
     58         return;
     59     }
     60 
     61     SkAutoUnref au(texture);
     62 
     63     SkIRect intScreen = SkIRect::MakeWH(kXSize, kYSize);
     64     SkRect screen;
     65 
     66     screen = SkRect::MakeWH(SkIntToScalar(kXSize),
     67                             SkIntToScalar(kYSize));
     68 
     69     SkRect clipRect(screen);
     70     clipRect.outset(10, 10);
     71 
     72     // create a clip stack that will (trivially) reduce to a single rect that
     73     // is larger than the screen
     74     SkClipStack stack;
     75     stack.clipDevRect(clipRect, SkRegion::kReplace_Op, false);
     76 
     77     bool isIntersectionOfRects = true;
     78     SkRect devStackBounds;
     79 
     80     stack.getConservativeBounds(0, 0, kXSize, kYSize,
     81                                 &devStackBounds,
     82                                 &isIntersectionOfRects);
     83 
     84     // make sure that the SkClipStack is behaving itself
     85     REPORTER_ASSERT(reporter, screen == devStackBounds);
     86     REPORTER_ASSERT(reporter, isIntersectionOfRects);
     87 
     88     // wrap the SkClipStack in a GrClipData
     89     GrClipData clipData;
     90     clipData.fClipStack = &stack;
     91 
     92     SkIRect devGrClipDataBound;
     93     clipData.getConservativeBounds(texture,
     94                                    &devGrClipDataBound,
     95                                    &isIntersectionOfRects);
     96 
     97     // make sure that GrClipData is behaving itself
     98     REPORTER_ASSERT(reporter, intScreen == devGrClipDataBound);
     99     REPORTER_ASSERT(reporter, isIntersectionOfRects);
    100 }
    101 
    102 ////////////////////////////////////////////////////////////////////////////////
    103 // verify that the top state of the stack matches the passed in state
    104 static void check_state(skiatest::Reporter* reporter,
    105                         const GrClipMaskCache& cache,
    106                         const SkClipStack& clip,
    107                         GrTexture* mask,
    108                         const SkIRect& bound) {
    109     REPORTER_ASSERT(reporter, clip.getTopmostGenID() == cache.getLastClipGenID());
    110 
    111     REPORTER_ASSERT(reporter, mask == cache.getLastMask());
    112 
    113     SkIRect cacheBound;
    114     cache.getLastBound(&cacheBound);
    115     REPORTER_ASSERT(reporter, bound == cacheBound);
    116 }
    117 
    118 static void check_empty_state(skiatest::Reporter* reporter,
    119                               const GrClipMaskCache& cache) {
    120     REPORTER_ASSERT(reporter, SkClipStack::kInvalidGenID == cache.getLastClipGenID());
    121     REPORTER_ASSERT(reporter, NULL == cache.getLastMask());
    122 
    123     SkIRect emptyBound;
    124     emptyBound.setEmpty();
    125 
    126     SkIRect cacheBound;
    127     cache.getLastBound(&cacheBound);
    128     REPORTER_ASSERT(reporter, emptyBound == cacheBound);
    129 }
    130 
    131 ////////////////////////////////////////////////////////////////////////////////
    132 // basic test of the cache's base functionality:
    133 //  push, pop, set, canReuse & getters
    134 static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
    135 
    136     if (false) { // avoid bit rot, suppress warning
    137         createTexture(context);
    138     }
    139     GrClipMaskCache cache;
    140 
    141     cache.setContext(context);
    142 
    143     // check initial state
    144     check_empty_state(reporter, cache);
    145 
    146     // set the current state
    147     SkIRect bound1;
    148     bound1.set(0, 0, 100, 100);
    149 
    150     SkClipStack clip1(bound1);
    151 
    152     GrTextureDesc desc;
    153     desc.fFlags = kRenderTarget_GrTextureFlagBit;
    154     desc.fWidth = X_SIZE;
    155     desc.fHeight = Y_SIZE;
    156     desc.fConfig = kSkia8888_GrPixelConfig;
    157 
    158     cache.acquireMask(clip1.getTopmostGenID(), desc, bound1);
    159 
    160     GrTexture* texture1 = cache.getLastMask();
    161     REPORTER_ASSERT(reporter, texture1);
    162     if (NULL == texture1) {
    163         return;
    164     }
    165 
    166     // check that the set took
    167     check_state(reporter, cache, clip1, texture1, bound1);
    168     REPORTER_ASSERT(reporter, texture1->getRefCnt());
    169 
    170     // push the state
    171     cache.push();
    172 
    173     // verify that the pushed state is initially empty
    174     check_empty_state(reporter, cache);
    175     REPORTER_ASSERT(reporter, texture1->getRefCnt());
    176 
    177     // modify the new state
    178     SkIRect bound2;
    179     bound2.set(-10, -10, 10, 10);
    180 
    181     SkClipStack clip2(bound2);
    182 
    183     cache.acquireMask(clip2.getTopmostGenID(), desc, bound2);
    184 
    185     GrTexture* texture2 = cache.getLastMask();
    186     REPORTER_ASSERT(reporter, texture2);
    187     if (NULL == texture2) {
    188         return;
    189     }
    190 
    191     // check that the changes took
    192     check_state(reporter, cache, clip2, texture2, bound2);
    193     REPORTER_ASSERT(reporter, texture1->getRefCnt());
    194     REPORTER_ASSERT(reporter, texture2->getRefCnt());
    195 
    196     // check to make sure canReuse works
    197     REPORTER_ASSERT(reporter, cache.canReuse(clip2.getTopmostGenID(), bound2));
    198     REPORTER_ASSERT(reporter, !cache.canReuse(clip1.getTopmostGenID(), bound1));
    199 
    200     // pop the state
    201     cache.pop();
    202 
    203     // verify that the old state is restored
    204     check_state(reporter, cache, clip1, texture1, bound1);
    205     REPORTER_ASSERT(reporter, texture1->getRefCnt());
    206 
    207     // manually clear the state
    208     cache.reset();
    209 
    210     // verify it is now empty
    211     check_empty_state(reporter, cache);
    212 
    213     // pop again - so there is no state
    214     cache.pop();
    215 
    216 #if !defined(SK_DEBUG)
    217     // verify that the getters don't crash
    218     // only do in release since it generates asserts in debug
    219     check_empty_state(reporter, cache);
    220 #endif
    221 }
    222 
    223 ////////////////////////////////////////////////////////////////////////////////
    224 static void TestClipCache(skiatest::Reporter* reporter, GrContextFactory* factory) {
    225     for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
    226         GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
    227         if (!GrContextFactory::IsRenderingGLContext(glType)) {
    228             continue;
    229         }
    230         GrContext* context = factory->get(glType);
    231         if (NULL == context) {
    232             continue;
    233         }
    234 
    235         test_cache(reporter, context);
    236         test_clip_bounds(reporter, context);
    237     }
    238 }
    239 
    240 ////////////////////////////////////////////////////////////////////////////////
    241 #include "TestClassDef.h"
    242 DEFINE_GPUTESTCLASS("ClipCache", ClipCacheTestClass, TestClipCache)
    243 
    244 #endif
    245