• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 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 here to ensure SK_SUPPORT_GPU is set correctly before it is examined.
9 #include "SkTypes.h"
10 
11 #if SK_SUPPORT_GPU
12 #ifndef SK_DISABLE_DEFERRED_PROXIES
13 #include "Test.h"
14 
15 #include "GrContextPriv.h"
16 #include "GrGpu.h"
17 #include "GrProxyProvider.h"
18 #include "GrResourceAllocator.h"
19 #include "GrResourceProvider.h"
20 #include "GrSurfaceProxyPriv.h"
21 #include "GrTest.h"
22 #include "GrTexture.h"
23 #include "GrTextureProxy.h"
24 
25 struct ProxyParams {
26     int             fSize;
27     bool            fIsRT;
28     GrPixelConfig   fConfig;
29     SkBackingFit    fFit;
30     int             fSampleCnt;
31     GrSurfaceOrigin fOrigin;
32     // TODO: do we care about mipmapping
33 };
34 
make_deferred(GrProxyProvider * proxyProvider,const ProxyParams & p)35 static sk_sp<GrSurfaceProxy> make_deferred(GrProxyProvider* proxyProvider, const ProxyParams& p) {
36     GrSurfaceDesc desc;
37     desc.fFlags = p.fIsRT ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
38     desc.fOrigin = p.fOrigin;
39     desc.fWidth  = p.fSize;
40     desc.fHeight = p.fSize;
41     desc.fConfig = p.fConfig;
42     desc.fSampleCnt = p.fSampleCnt;
43 
44     return proxyProvider->createProxy(desc, p.fFit, SkBudgeted::kNo);
45 }
46 
make_backend(GrContext * context,const ProxyParams & p,GrBackendTexture * backendTex)47 static sk_sp<GrSurfaceProxy> make_backend(GrContext* context, const ProxyParams& p,
48                                           GrBackendTexture* backendTex) {
49     GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
50     GrGpu* gpu = context->contextPriv().getGpu();
51 
52     *backendTex = gpu->createTestingOnlyBackendTexture(nullptr, p.fSize, p.fSize,
53                                                        p.fConfig, false,
54                                                        GrMipMapped::kNo);
55 
56     return proxyProvider->createWrappedTextureProxy(*backendTex, p.fOrigin);
57 }
58 
cleanup_backend(GrContext * context,GrBackendTexture * backendTex)59 static void cleanup_backend(GrContext* context, GrBackendTexture* backendTex) {
60     context->contextPriv().getGpu()->deleteTestingOnlyBackendTexture(backendTex);
61 }
62 
63 // Basic test that two proxies with overlapping intervals and compatible descriptors are
64 // assigned different GrSurfaces.
overlap_test(skiatest::Reporter * reporter,GrResourceProvider * resourceProvider,sk_sp<GrSurfaceProxy> p1,sk_sp<GrSurfaceProxy> p2,bool expectedResult)65 static void overlap_test(skiatest::Reporter* reporter, GrResourceProvider* resourceProvider,
66                          sk_sp<GrSurfaceProxy> p1, sk_sp<GrSurfaceProxy> p2,
67                          bool expectedResult) {
68     GrResourceAllocator alloc(resourceProvider);
69 
70     alloc.addInterval(p1.get(), 0, 4);
71     alloc.addInterval(p2.get(), 1, 2);
72     alloc.markEndOfOpList(0);
73 
74     int startIndex, stopIndex;
75     GrResourceAllocator::AssignError error;
76     alloc.assign(&startIndex, &stopIndex, &error);
77     REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
78 
79     REPORTER_ASSERT(reporter, p1->priv().peekSurface());
80     REPORTER_ASSERT(reporter, p2->priv().peekSurface());
81     bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID();
82     REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch);
83 }
84 
85 // Test various cases when two proxies do not have overlapping intervals.
86 // This mainly acts as a test of the ResourceAllocator's free pool.
non_overlap_test(skiatest::Reporter * reporter,GrResourceProvider * resourceProvider,sk_sp<GrSurfaceProxy> p1,sk_sp<GrSurfaceProxy> p2,bool expectedResult)87 static void non_overlap_test(skiatest::Reporter* reporter, GrResourceProvider* resourceProvider,
88                              sk_sp<GrSurfaceProxy> p1, sk_sp<GrSurfaceProxy> p2,
89                              bool expectedResult) {
90     GrResourceAllocator alloc(resourceProvider);
91 
92     alloc.addInterval(p1.get(), 0, 2);
93     alloc.addInterval(p2.get(), 3, 5);
94     alloc.markEndOfOpList(0);
95 
96     int startIndex, stopIndex;
97     GrResourceAllocator::AssignError error;
98     alloc.assign(&startIndex, &stopIndex, &error);
99     REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
100 
101     REPORTER_ASSERT(reporter, p1->priv().peekSurface());
102     REPORTER_ASSERT(reporter, p2->priv().peekSurface());
103     bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID();
104     REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch);
105 }
106 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorTest,reporter,ctxInfo)107 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorTest, reporter, ctxInfo) {
108     GrProxyProvider* proxyProvider = ctxInfo.grContext()->contextPriv().proxyProvider();
109     GrResourceProvider* resourceProvider = ctxInfo.grContext()->contextPriv().resourceProvider();
110 
111     struct TestCase {
112         ProxyParams   fP1;
113         ProxyParams   fP2;
114         bool          fExpectation;
115     };
116 
117     constexpr bool kRT = true;
118     constexpr bool kNotRT = false;
119 
120     constexpr bool kShare = true;
121     constexpr bool kDontShare = false;
122     // Non-RT GrSurfaces are never recycled on some platforms.
123     bool kConditionallyShare = resourceProvider->caps()->reuseScratchTextures();
124 
125     const GrPixelConfig kRGBA = kRGBA_8888_GrPixelConfig;
126     const GrPixelConfig kBGRA = kBGRA_8888_GrPixelConfig;
127 
128     const SkBackingFit kE = SkBackingFit::kExact;
129     const SkBackingFit kA = SkBackingFit::kApprox;
130 
131     const GrSurfaceOrigin kTL = kTopLeft_GrSurfaceOrigin;
132     const GrSurfaceOrigin kBL = kBottomLeft_GrSurfaceOrigin;
133 
134     //--------------------------------------------------------------------------------------------
135     TestCase gOverlappingTests[] = {
136         //----------------------------------------------------------------------------------------
137         // Two proxies with overlapping intervals and compatible descriptors should never share
138         // RT version
139         { { 64,    kRT, kRGBA, kA, 0, kTL }, { 64,    kRT, kRGBA, kA, 0, kTL }, kDontShare },
140         // non-RT version
141         { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kDontShare },
142     };
143 
144     for (auto test : gOverlappingTests) {
145         sk_sp<GrSurfaceProxy> p1 = make_deferred(proxyProvider, test.fP1);
146         sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, test.fP2);
147         overlap_test(reporter, resourceProvider,
148                      std::move(p1), std::move(p2), test.fExpectation);
149     }
150 
151     int k2 = ctxInfo.grContext()->caps()->getSampleCount(2, kRGBA);
152     int k4 = ctxInfo.grContext()->caps()->getSampleCount(4, kRGBA);
153 
154     //--------------------------------------------------------------------------------------------
155     TestCase gNonOverlappingTests[] = {
156         //----------------------------------------------------------------------------------------
157         // Two non-overlapping intervals w/ compatible proxies should share
158         // both same size & approx
159         { { 64,    kRT, kRGBA, kA, 0, kTL }, { 64,    kRT, kRGBA, kA, 0, kTL }, kShare },
160         { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kConditionallyShare },
161         // diffs sizes but still approx
162         { { 64,    kRT, kRGBA, kA, 0, kTL }, { 50,    kRT, kRGBA, kA, 0, kTL }, kShare },
163         { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 50, kNotRT, kRGBA, kA, 0, kTL }, kConditionallyShare },
164         // sames sizes but exact
165         { { 64,    kRT, kRGBA, kE, 0, kTL }, { 64,    kRT, kRGBA, kE, 0, kTL }, kShare },
166         { { 64, kNotRT, kRGBA, kE, 0, kTL }, { 64, kNotRT, kRGBA, kE, 0, kTL }, kConditionallyShare },
167         //----------------------------------------------------------------------------------------
168         // Two non-overlapping intervals w/ different exact sizes should not share
169         { { 56,    kRT, kRGBA, kE, 0, kTL }, { 54,    kRT, kRGBA, kE, 0, kTL }, kDontShare },
170         // Two non-overlapping intervals w/ _very different_ approx sizes should not share
171         { { 255,   kRT, kRGBA, kA, 0, kTL }, { 127,   kRT, kRGBA, kA, 0, kTL }, kDontShare },
172         // Two non-overlapping intervals w/ different MSAA sample counts should not share
173         { { 64,    kRT, kRGBA, kA, k2, kTL },{ 64,    kRT, kRGBA, kA, k4, kTL}, k2 == k4 },
174         // Two non-overlapping intervals w/ different configs should not share
175         { { 64,    kRT, kRGBA, kA, 0, kTL }, { 64,    kRT, kBGRA, kA, 0, kTL }, kDontShare },
176         // Two non-overlapping intervals w/ different RT classifications should never share
177         { { 64,    kRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kDontShare },
178         { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64,    kRT, kRGBA, kA, 0, kTL }, kDontShare },
179         // Two non-overlapping intervals w/ different origins should share
180         { { 64,    kRT, kRGBA, kA, 0, kTL }, { 64,    kRT, kRGBA, kA, 0, kBL }, kShare },
181     };
182 
183     for (auto test : gNonOverlappingTests) {
184         sk_sp<GrSurfaceProxy> p1 = make_deferred(proxyProvider, test.fP1);
185         sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, test.fP2);
186         if (!p1 || !p2) {
187             continue; // creation can fail (i.e., for msaa4 on iOS)
188         }
189         non_overlap_test(reporter, resourceProvider,
190                          std::move(p1), std::move(p2), test.fExpectation);
191     }
192 
193     {
194         // Wrapped backend textures should never be reused
195         TestCase t[1] = {
196             { { 64, kNotRT, kRGBA, kE, 0, kTL }, { 64, kNotRT, kRGBA, kE, 0, kTL }, kDontShare }
197         };
198 
199         GrBackendTexture backEndTex;
200         sk_sp<GrSurfaceProxy> p1 = make_backend(ctxInfo.grContext(), t[0].fP1, &backEndTex);
201         sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, t[0].fP2);
202         non_overlap_test(reporter, resourceProvider,
203                          std::move(p1), std::move(p2), t[0].fExpectation);
204         cleanup_backend(ctxInfo.grContext(), &backEndTex);
205     }
206 }
207 
208 #endif
209 #endif
210