• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 // This is a GPU-backend specific test.
9 
10 #include "Test.h"
11 
12 #if SK_SUPPORT_GPU
13 
14 #include "GrBackendSurface.h"
15 #include "GrContextPriv.h"
16 #include "GrProxyProvider.h"
17 #include "GrRenderTargetPriv.h"
18 #include "GrRenderTargetProxy.h"
19 #include "GrResourceProvider.h"
20 #include "GrSurfaceProxyPriv.h"
21 #include "GrTexture.h"
22 #include "GrTextureProxy.h"
23 
24 // Check that the surface proxy's member vars are set as expected
check_surface(skiatest::Reporter * reporter,GrSurfaceProxy * proxy,GrSurfaceOrigin origin,int width,int height,GrPixelConfig config,SkBudgeted budgeted)25 static void check_surface(skiatest::Reporter* reporter,
26                           GrSurfaceProxy* proxy,
27                           GrSurfaceOrigin origin,
28                           int width, int height,
29                           GrPixelConfig config,
30                           SkBudgeted budgeted) {
31     REPORTER_ASSERT(reporter, proxy->origin() == origin);
32     REPORTER_ASSERT(reporter, proxy->width() == width);
33     REPORTER_ASSERT(reporter, proxy->height() == height);
34     REPORTER_ASSERT(reporter, proxy->config() == config);
35     REPORTER_ASSERT(reporter, !proxy->uniqueID().isInvalid());
36     REPORTER_ASSERT(reporter, proxy->isBudgeted() == budgeted);
37 }
38 
check_rendertarget(skiatest::Reporter * reporter,const GrCaps & caps,GrResourceProvider * provider,GrRenderTargetProxy * rtProxy,int numSamples,SkBackingFit fit,int expectedMaxWindowRects,bool wasWrapped)39 static void check_rendertarget(skiatest::Reporter* reporter,
40                                const GrCaps& caps,
41                                GrResourceProvider* provider,
42                                GrRenderTargetProxy* rtProxy,
43                                int numSamples,
44                                SkBackingFit fit,
45                                int expectedMaxWindowRects,
46                                bool wasWrapped) {
47     REPORTER_ASSERT(reporter, rtProxy->maxWindowRectangles(caps) == expectedMaxWindowRects);
48     REPORTER_ASSERT(reporter, rtProxy->numStencilSamples() == numSamples);
49 
50     GrSurfaceProxy::UniqueID idBefore = rtProxy->uniqueID();
51     REPORTER_ASSERT(reporter, rtProxy->instantiate(provider));
52     GrRenderTarget* rt = rtProxy->priv().peekRenderTarget();
53 
54     REPORTER_ASSERT(reporter, rtProxy->uniqueID() == idBefore);
55     if (wasWrapped) {
56         // Wrapped resources share their uniqueID with the wrapping RenderTargetProxy
57         REPORTER_ASSERT(reporter, rtProxy->uniqueID().asUInt() == rt->uniqueID().asUInt());
58     } else {
59         // Deferred resources should always have a different ID from their instantiated rendertarget
60         REPORTER_ASSERT(reporter, rtProxy->uniqueID().asUInt() != rt->uniqueID().asUInt());
61     }
62 
63     if (SkBackingFit::kExact == fit) {
64         REPORTER_ASSERT(reporter, rt->width() == rtProxy->width());
65         REPORTER_ASSERT(reporter, rt->height() == rtProxy->height());
66     } else {
67         REPORTER_ASSERT(reporter, rt->width() >= rtProxy->width());
68         REPORTER_ASSERT(reporter, rt->height() >= rtProxy->height());
69     }
70     REPORTER_ASSERT(reporter, rt->config() == rtProxy->config());
71 
72     REPORTER_ASSERT(reporter, rt->fsaaType() == rtProxy->fsaaType());
73     REPORTER_ASSERT(reporter, rt->numColorSamples() == rtProxy->numColorSamples());
74     REPORTER_ASSERT(reporter, rt->numStencilSamples() == rtProxy->numStencilSamples());
75     REPORTER_ASSERT(reporter, rt->renderTargetPriv().flags() == rtProxy->testingOnly_getFlags());
76 }
77 
check_texture(skiatest::Reporter * reporter,GrResourceProvider * provider,GrTextureProxy * texProxy,SkBackingFit fit,bool wasWrapped)78 static void check_texture(skiatest::Reporter* reporter,
79                           GrResourceProvider* provider,
80                           GrTextureProxy* texProxy,
81                           SkBackingFit fit,
82                           bool wasWrapped) {
83     GrSurfaceProxy::UniqueID idBefore = texProxy->uniqueID();
84 
85     REPORTER_ASSERT(reporter, texProxy->instantiate(provider));
86     GrTexture* tex = texProxy->priv().peekTexture();
87 
88     REPORTER_ASSERT(reporter, texProxy->uniqueID() == idBefore);
89     if (wasWrapped) {
90         // Wrapped resources share their uniqueID with the wrapping TextureProxy
91         REPORTER_ASSERT(reporter, texProxy->uniqueID().asUInt() == tex->uniqueID().asUInt());
92     } else {
93         // Deferred resources should always have a different ID from their instantiated texture
94         REPORTER_ASSERT(reporter, texProxy->uniqueID().asUInt() != tex->uniqueID().asUInt());
95     }
96 
97     if (SkBackingFit::kExact == fit) {
98         REPORTER_ASSERT(reporter, tex->width() == texProxy->width());
99         REPORTER_ASSERT(reporter, tex->height() == texProxy->height());
100     } else {
101         REPORTER_ASSERT(reporter, tex->width() >= texProxy->width());
102         REPORTER_ASSERT(reporter, tex->height() >= texProxy->height());
103     }
104     REPORTER_ASSERT(reporter, tex->config() == texProxy->config());
105 }
106 
107 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredProxyTest,reporter,ctxInfo)108 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredProxyTest, reporter, ctxInfo) {
109     GrProxyProvider* proxyProvider = ctxInfo.grContext()->contextPriv().proxyProvider();
110     GrResourceProvider* resourceProvider = ctxInfo.grContext()->contextPriv().resourceProvider();
111     const GrCaps& caps = *ctxInfo.grContext()->caps();
112 
113     int attempt = 0; // useful for debugging
114 
115     for (auto origin : { kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin }) {
116         for (auto widthHeight : { 100, 128, 1048576 }) {
117             for (auto config : { kAlpha_8_GrPixelConfig, kRGB_565_GrPixelConfig,
118                                  kRGBA_8888_GrPixelConfig }) {
119                 for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
120                     for (auto budgeted : { SkBudgeted::kYes, SkBudgeted::kNo }) {
121                         for (auto numSamples : {1, 4, 16, 128}) {
122                             GrSurfaceDesc desc;
123                             desc.fFlags = kRenderTarget_GrSurfaceFlag;
124                             desc.fOrigin = origin;
125                             desc.fWidth = widthHeight;
126                             desc.fHeight = widthHeight;
127                             desc.fConfig = config;
128                             desc.fSampleCnt = numSamples;
129 
130                             {
131                                 sk_sp<GrTexture> tex;
132                                 if (SkBackingFit::kApprox == fit) {
133                                     tex = resourceProvider->createApproxTexture(desc, 0);
134                                 } else {
135                                     tex = resourceProvider->createTexture(desc, budgeted);
136                                 }
137 
138                                 sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(
139                                                                             desc, fit, budgeted);
140                                 REPORTER_ASSERT(reporter, SkToBool(tex) == SkToBool(proxy));
141                                 if (proxy) {
142                                     REPORTER_ASSERT(reporter, proxy->asRenderTargetProxy());
143                                     // This forces the proxy to compute and cache its
144                                     // pre-instantiation size guess. Later, when it is actually
145                                     // instantiated, it checks that the instantiated size is <= to
146                                     // the pre-computation. If the proxy never computed its
147                                     // pre-instantiation size then the check is skipped.
148                                     proxy->gpuMemorySize();
149 
150                                     check_surface(reporter, proxy.get(), origin,
151                                                   widthHeight, widthHeight, config, budgeted);
152                                     int supportedSamples = caps.getSampleCount(numSamples, config);
153                                     check_rendertarget(reporter, caps, resourceProvider,
154                                                        proxy->asRenderTargetProxy(),
155                                                        supportedSamples,
156                                                        fit, caps.maxWindowRectangles(), false);
157                                 }
158                             }
159 
160                             desc.fFlags = kNone_GrSurfaceFlags;
161 
162                             {
163                                 sk_sp<GrTexture> tex;
164                                 if (SkBackingFit::kApprox == fit) {
165                                     tex = resourceProvider->createApproxTexture(desc, 0);
166                                 } else {
167                                     tex = resourceProvider->createTexture(desc, budgeted);
168                                 }
169 
170                                 sk_sp<GrTextureProxy> proxy(proxyProvider->createProxy(
171                                                                             desc, fit, budgeted));
172                                 REPORTER_ASSERT(reporter, SkToBool(tex) == SkToBool(proxy));
173                                 if (proxy) {
174                                     // This forces the proxy to compute and cache its
175                                     // pre-instantiation size guess. Later, when it is actually
176                                     // instantiated, it checks that the instantiated size is <= to
177                                     // the pre-computation. If the proxy never computed its
178                                     // pre-instantiation size then the check is skipped.
179                                     proxy->gpuMemorySize();
180 
181                                     check_surface(reporter, proxy.get(), origin,
182                                                   widthHeight, widthHeight, config, budgeted);
183                                     check_texture(reporter, resourceProvider,
184                                                   proxy->asTextureProxy(), fit, false);
185                                 }
186                             }
187 
188                             attempt++;
189                         }
190                     }
191                 }
192             }
193         }
194     }
195 }
196 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest,reporter,ctxInfo)197 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) {
198     GrProxyProvider* proxyProvider = ctxInfo.grContext()->contextPriv().proxyProvider();
199     GrResourceProvider* resourceProvider = ctxInfo.grContext()->contextPriv().resourceProvider();
200     const GrCaps& caps = *ctxInfo.grContext()->caps();
201 
202     static const int kWidthHeight = 100;
203 
204     for (auto origin : { kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin }) {
205         for (auto config : { kAlpha_8_GrPixelConfig, kRGBA_8888_GrPixelConfig }) {
206             for (auto budgeted : { SkBudgeted::kYes, SkBudgeted::kNo }) {
207                 for (auto numSamples : {1, 4}) {
208                     int supportedNumSamples = caps.getSampleCount(numSamples, config);
209 
210                     bool renderable = caps.isConfigRenderable(config, numSamples > 1);
211 
212                     GrSurfaceDesc desc;
213                     desc.fOrigin = origin;
214                     desc.fWidth = kWidthHeight;
215                     desc.fHeight = kWidthHeight;
216                     desc.fConfig = config;
217                     desc.fSampleCnt = supportedNumSamples;
218 
219                     // External on-screen render target.
220                     if (renderable && kOpenGL_GrBackend == ctxInfo.backend()) {
221                         GrGLFramebufferInfo fboInfo;
222                         fboInfo.fFBOID = 0;
223                         GrBackendRenderTarget backendRT(kWidthHeight, kWidthHeight, numSamples, 8,
224                                                         config, fboInfo);
225 
226                         sk_sp<GrSurfaceProxy> sProxy(proxyProvider->createWrappedRenderTargetProxy(
227                                                                                 backendRT, origin));
228                         check_surface(reporter, sProxy.get(), origin,
229                                       kWidthHeight, kWidthHeight, config, SkBudgeted::kNo);
230                         check_rendertarget(reporter, caps, resourceProvider,
231                                            sProxy->asRenderTargetProxy(),
232                                            supportedNumSamples, SkBackingFit::kExact, 0, true);
233                     }
234 
235                     if (renderable) {
236                         // Internal offscreen render target.
237                         desc.fFlags = kRenderTarget_GrSurfaceFlag;
238 
239                         sk_sp<GrSurfaceProxy> sProxy = proxyProvider->createInstantiatedProxy(
240                                                         desc, SkBackingFit::kExact, budgeted);
241                         if (!sProxy) {
242                             continue;  // This can fail on Mesa
243                         }
244 
245                         check_surface(reporter, sProxy.get(), origin,
246                                       kWidthHeight, kWidthHeight, config, budgeted);
247                         check_rendertarget(reporter, caps, resourceProvider,
248                                            sProxy->asRenderTargetProxy(),
249                                            supportedNumSamples, SkBackingFit::kExact,
250                                            caps.maxWindowRectangles(), true);
251                     } else {
252                         // Internal offscreen texture
253                         SkASSERT(kNone_GrSurfaceFlags == desc.fFlags );
254                         desc.fSampleCnt = 1;
255 
256                         sk_sp<GrSurfaceProxy> sProxy = proxyProvider->createInstantiatedProxy(
257                                                           desc, SkBackingFit::kExact, budgeted);
258                         if (!sProxy) {
259                             continue;
260                         }
261 
262                         check_surface(reporter, sProxy.get(), origin,
263                                       kWidthHeight, kWidthHeight, config, budgeted);
264                         check_texture(reporter, resourceProvider, sProxy->asTextureProxy(),
265                                       SkBackingFit::kExact, true);
266                     }
267                 }
268             }
269         }
270     }
271 }
272 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ZeroSizedProxyTest,reporter,ctxInfo)273 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ZeroSizedProxyTest, reporter, ctxInfo) {
274     GrProxyProvider* provider = ctxInfo.grContext()->contextPriv().proxyProvider();
275 
276     for (auto flags : { kRenderTarget_GrSurfaceFlag, kNone_GrSurfaceFlags }) {
277         for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
278             for (int width : { 0, 100 }) {
279                 for (int height : { 0, 100}) {
280                     if (width && height) {
281                         continue; // not zero-sized
282                     }
283 
284                     GrSurfaceDesc desc;
285                     desc.fFlags = flags;
286                     desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
287                     desc.fWidth = width;
288                     desc.fHeight = height;
289                     desc.fConfig = kRGBA_8888_GrPixelConfig;
290                     desc.fSampleCnt = 1;
291 
292                     sk_sp<GrTextureProxy> proxy = provider->createProxy(desc, fit, SkBudgeted::kNo);
293                     REPORTER_ASSERT(reporter, !proxy);
294                 }
295             }
296         }
297     }
298 }
299 
300 #endif
301