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