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