ClipCacheTest.cpp revision f0784bde753feaff601f703089872fc1af265328
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    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
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
201    // manually clear the state
202    cache.reset();
203
204    // verify it is now empty
205    check_state(reporter, cache, emptyClip, NULL, emptyBound);
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}
216
217////////////////////////////////////////////////////////////////////////////////
218static void TestClipCache(skiatest::Reporter* reporter, GrContextFactory* factory) {
219    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
220        GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
221        if (!GrContextFactory::IsRenderingGLContext(glType)) {
222            continue;
223        }
224        GrContext* context = factory->get(glType);
225        if (NULL == context) {
226            continue;
227        }
228
229        test_cache(reporter, context);
230        test_clip_bounds(reporter, context);
231    }
232}
233
234////////////////////////////////////////////////////////////////////////////////
235#include "TestClassDef.h"
236DEFINE_GPUTESTCLASS("ClipCache", ClipCacheTestClass, TestClipCache)
237
238#endif
239