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 16static const int X_SIZE = 12; 17static const int Y_SIZE = 12; 18 19//////////////////////////////////////////////////////////////////////////////// 20// note: this is unused 21static 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 45static 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 GrAutoUnref 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 104static void check_state(skiatest::Reporter* reporter, 105 const GrClipMaskCache& cache, 106 const SkClipStack& clip, 107 GrTexture* mask, 108 const SkIRect& bound) { 109 SkClipStack cacheClip; 110 REPORTER_ASSERT(reporter, clip.getTopmostGenID() == cache.getLastClipGenID()); 111 112 REPORTER_ASSERT(reporter, mask == cache.getLastMask()); 113 114 SkIRect cacheBound; 115 cache.getLastBound(&cacheBound); 116 REPORTER_ASSERT(reporter, bound == cacheBound); 117} 118 119//////////////////////////////////////////////////////////////////////////////// 120// basic test of the cache's base functionality: 121// push, pop, set, canReuse & getters 122static void test_cache(skiatest::Reporter* reporter, GrContext* context) { 123 124 if (false) { // avoid bit rot, suppress warning 125 createTexture(context); 126 } 127 GrClipMaskCache cache; 128 129 cache.setContext(context); 130 131 SkClipStack emptyClip; 132 emptyClip.reset(); 133 134 SkIRect emptyBound; 135 emptyBound.setEmpty(); 136 137 // check initial state 138 check_state(reporter, cache, emptyClip, NULL, emptyBound); 139 140 // set the current state 141 SkIRect bound1; 142 bound1.set(0, 0, 100, 100); 143 144 SkClipStack clip1(bound1); 145 146 GrTextureDesc desc; 147 desc.fFlags = kRenderTarget_GrTextureFlagBit; 148 desc.fWidth = X_SIZE; 149 desc.fHeight = Y_SIZE; 150 desc.fConfig = kSkia8888_GrPixelConfig; 151 152 cache.acquireMask(clip1.getTopmostGenID(), desc, bound1); 153 154 GrTexture* texture1 = cache.getLastMask(); 155 REPORTER_ASSERT(reporter, texture1); 156 if (NULL == texture1) { 157 return; 158 } 159 160 // check that the set took 161 check_state(reporter, cache, clip1, texture1, bound1); 162 REPORTER_ASSERT(reporter, texture1->getRefCnt()); 163 164 // push the state 165 cache.push(); 166 167 // verify that the pushed state is initially empty 168 check_state(reporter, cache, emptyClip, NULL, emptyBound); 169 REPORTER_ASSERT(reporter, texture1->getRefCnt()); 170 171 // modify the new state 172 SkIRect bound2; 173 bound2.set(-10, -10, 10, 10); 174 175 SkClipStack clip2(bound2); 176 177 cache.acquireMask(clip2.getTopmostGenID(), desc, bound2); 178 179 GrTexture* texture2 = cache.getLastMask(); 180 REPORTER_ASSERT(reporter, texture2); 181 if (NULL == texture2) { 182 return; 183 } 184 185 // check that the changes took 186 check_state(reporter, cache, clip2, texture2, bound2); 187 REPORTER_ASSERT(reporter, texture1->getRefCnt()); 188 REPORTER_ASSERT(reporter, texture2->getRefCnt()); 189 190 // check to make sure canReuse works 191 REPORTER_ASSERT(reporter, cache.canReuse(clip2.getTopmostGenID(), bound2)); 192 REPORTER_ASSERT(reporter, !cache.canReuse(clip1.getTopmostGenID(), bound1)); 193 194 // pop the state 195 cache.pop(); 196 197 // verify that the old state is restored 198 check_state(reporter, cache, clip1, texture1, bound1); 199 REPORTER_ASSERT(reporter, texture1->getRefCnt()); 200 REPORTER_ASSERT(reporter, texture2->getRefCnt()); 201 202 // manually clear the state 203 cache.reset(); 204 205 // verify it is now empty 206 check_state(reporter, cache, emptyClip, NULL, emptyBound); 207 REPORTER_ASSERT(reporter, texture1->getRefCnt()); 208 REPORTER_ASSERT(reporter, texture2->getRefCnt()); 209 210 // pop again - so there is no state 211 cache.pop(); 212 213#if !defined(SK_DEBUG) 214 // verify that the getters don't crash 215 // only do in release since it generates asserts in debug 216 check_state(reporter, cache, emptyClip, NULL, emptyBound); 217#endif 218 REPORTER_ASSERT(reporter, texture1->getRefCnt()); 219 REPORTER_ASSERT(reporter, texture2->getRefCnt()); 220} 221 222//////////////////////////////////////////////////////////////////////////////// 223static void TestClipCache(skiatest::Reporter* reporter, GrContextFactory* factory) { 224 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { 225 GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type); 226 if (!GrContextFactory::IsRenderingGLContext(glType)) { 227 continue; 228 } 229 GrContext* context = factory->get(glType); 230 if (NULL == context) { 231 continue; 232 } 233 234 test_cache(reporter, context); 235 test_clip_bounds(reporter, context); 236 } 237} 238 239//////////////////////////////////////////////////////////////////////////////// 240#include "TestClassDef.h" 241DEFINE_GPUTESTCLASS("ClipCache", ClipCacheTestClass, TestClipCache) 242 243#endif 244