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