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