ClipCacheTest.cpp revision fec0bc3fc13481f5bcb341ab2d2d695911f39bd4
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 = SkRect::MakeWH(SkIntToScalar(kXSize),
65                                   SkIntToScalar(kYSize));
66    SkRect clipRect(screen);
67    clipRect.outset(10, 10);
68
69    // create a clip stack that will (trivially) reduce to a single rect that
70    // is larger than the screen
71    SkClipStack stack;
72    stack.clipDevRect(clipRect, SkRegion::kReplace_Op, false);
73
74    bool isIntersectionOfRects = true;
75    SkRect devStackBounds;
76
77    stack.getConservativeBounds(0, 0, kXSize, kYSize,
78                                &devStackBounds,
79                                &isIntersectionOfRects);
80
81    // make sure that the SkClipStack is behaving itself
82    REPORTER_ASSERT(reporter, screen == devStackBounds);
83    REPORTER_ASSERT(reporter, isIntersectionOfRects);
84
85    // wrap the SkClipStack in a GrClipData
86    GrClipData clipData;
87    clipData.fClipStack = &stack;
88
89    SkIRect devGrClipDataBound;
90    clipData.getConservativeBounds(texture,
91                                   &devGrClipDataBound,
92                                   &isIntersectionOfRects);
93
94    // make sure that GrClipData is behaving itself
95    REPORTER_ASSERT(reporter, intScreen == devGrClipDataBound);
96    REPORTER_ASSERT(reporter, isIntersectionOfRects);
97}
98
99////////////////////////////////////////////////////////////////////////////////
100// verify that the top state of the stack matches the passed in state
101static void check_state(skiatest::Reporter* reporter,
102                        const GrClipMaskCache& cache,
103                        const SkClipStack& clip,
104                        GrTexture* mask,
105                        const GrIRect& bound) {
106    SkClipStack cacheClip;
107    REPORTER_ASSERT(reporter, clip.getTopmostGenID() == cache.getLastClipGenID());
108
109    REPORTER_ASSERT(reporter, mask == cache.getLastMask());
110
111    GrIRect cacheBound;
112    cache.getLastBound(&cacheBound);
113    REPORTER_ASSERT(reporter, bound == cacheBound);
114}
115
116////////////////////////////////////////////////////////////////////////////////
117// basic test of the cache's base functionality:
118//  push, pop, set, canReuse & getters
119static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
120
121    if (false) { // avoid bit rot, suppress warning
122        createTexture(context);
123    }
124    GrClipMaskCache cache;
125
126    cache.setContext(context);
127
128    SkClipStack emptyClip;
129    emptyClip.reset();
130
131    GrIRect emptyBound;
132    emptyBound.setEmpty();
133
134    // check initial state
135    check_state(reporter, cache, emptyClip, NULL, emptyBound);
136
137    // set the current state
138    GrIRect bound1;
139    bound1.set(0, 0, 100, 100);
140
141    SkClipStack clip1(bound1);
142
143    GrTextureDesc desc;
144    desc.fFlags = kRenderTarget_GrTextureFlagBit;
145    desc.fWidth = X_SIZE;
146    desc.fHeight = Y_SIZE;
147    desc.fConfig = kSkia8888_GrPixelConfig;
148
149    cache.acquireMask(clip1.getTopmostGenID(), desc, bound1);
150
151    GrTexture* texture1 = cache.getLastMask();
152    REPORTER_ASSERT(reporter, texture1);
153    if (NULL == texture1) {
154        return;
155    }
156
157    // check that the set took
158    check_state(reporter, cache, clip1, texture1, bound1);
159    REPORTER_ASSERT(reporter, texture1->getRefCnt());
160
161    // push the state
162    cache.push();
163
164    // verify that the pushed state is initially empty
165    check_state(reporter, cache, emptyClip, NULL, emptyBound);
166    REPORTER_ASSERT(reporter, texture1->getRefCnt());
167
168    // modify the new state
169    GrIRect bound2;
170    bound2.set(-10, -10, 10, 10);
171
172    SkClipStack clip2(bound2);
173
174    cache.acquireMask(clip2.getTopmostGenID(), desc, bound2);
175
176    GrTexture* texture2 = cache.getLastMask();
177    REPORTER_ASSERT(reporter, texture2);
178    if (NULL == texture2) {
179        return;
180    }
181
182    // check that the changes took
183    check_state(reporter, cache, clip2, texture2, bound2);
184    REPORTER_ASSERT(reporter, texture1->getRefCnt());
185    REPORTER_ASSERT(reporter, texture2->getRefCnt());
186
187    // check to make sure canReuse works
188    REPORTER_ASSERT(reporter, cache.canReuse(clip2.getTopmostGenID(), bound2));
189    REPORTER_ASSERT(reporter, !cache.canReuse(clip1.getTopmostGenID(), bound1));
190
191    // pop the state
192    cache.pop();
193
194    // verify that the old state is restored
195    check_state(reporter, cache, clip1, texture1, bound1);
196    REPORTER_ASSERT(reporter, texture1->getRefCnt());
197    REPORTER_ASSERT(reporter, texture2->getRefCnt());
198
199    // manually clear the state
200    cache.reset();
201
202    // verify it is now empty
203    check_state(reporter, cache, emptyClip, NULL, emptyBound);
204    REPORTER_ASSERT(reporter, texture1->getRefCnt());
205    REPORTER_ASSERT(reporter, texture2->getRefCnt());
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_state(reporter, cache, emptyClip, NULL, emptyBound);
214#endif
215    REPORTER_ASSERT(reporter, texture1->getRefCnt());
216    REPORTER_ASSERT(reporter, texture2->getRefCnt());
217}
218
219////////////////////////////////////////////////////////////////////////////////
220static void TestClipCache(skiatest::Reporter* reporter, GrContextFactory* factory) {
221    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
222        GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
223        if (!GrContextFactory::IsRenderingGLContext(glType)) {
224            continue;
225        }
226        GrContext* context = factory->get(glType);
227        if (NULL == context) {
228            continue;
229        }
230
231        test_cache(reporter, context);
232        test_clip_bounds(reporter, context);
233    }
234}
235
236////////////////////////////////////////////////////////////////////////////////
237#include "TestClassDef.h"
238DEFINE_GPUTESTCLASS("ClipCache", ClipCacheTestClass, TestClipCache)
239
240#endif
241