• 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 "tests/Test.h"
11 
12 #include "include/gpu/GrBackendSurface.h"
13 #include "include/gpu/GrTexture.h"
14 #include "src/gpu/GrContextPriv.h"
15 #include "src/gpu/GrProxyProvider.h"
16 #include "src/gpu/GrRenderTargetPriv.h"
17 #include "src/gpu/GrRenderTargetProxy.h"
18 #include "src/gpu/GrResourceProvider.h"
19 #include "src/gpu/GrSurfacePriv.h"
20 #include "src/gpu/GrSurfaceProxyPriv.h"
21 #include "src/gpu/GrTextureProxy.h"
22 #include "src/gpu/SkGr.h"
23 #include "src/gpu/gl/GrGLDefines.h"
24 #include "src/gpu/gl/GrGLUtil.h"
25 
26 // 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)27 static void check_surface(skiatest::Reporter* reporter,
28                           GrSurfaceProxy* proxy,
29                           GrSurfaceOrigin origin,
30                           int width, int height,
31                           GrPixelConfig config,
32                           SkBudgeted budgeted) {
33     REPORTER_ASSERT(reporter, proxy->origin() == origin);
34     REPORTER_ASSERT(reporter, proxy->width() == width);
35     REPORTER_ASSERT(reporter, proxy->height() == height);
36 #ifdef SK_DEBUG
37     REPORTER_ASSERT(reporter, GrCaps::AreConfigsCompatible(config, proxy->config()));
38 #endif
39     REPORTER_ASSERT(reporter, !proxy->uniqueID().isInvalid());
40     REPORTER_ASSERT(reporter, proxy->isBudgeted() == budgeted);
41 }
42 
check_rendertarget(skiatest::Reporter * reporter,const GrCaps & caps,GrResourceProvider * provider,GrRenderTargetProxy * rtProxy,int numSamples,SkBackingFit fit,int expectedMaxWindowRects)43 static void check_rendertarget(skiatest::Reporter* reporter,
44                                const GrCaps& caps,
45                                GrResourceProvider* provider,
46                                GrRenderTargetProxy* rtProxy,
47                                int numSamples,
48                                SkBackingFit fit,
49                                int expectedMaxWindowRects) {
50     REPORTER_ASSERT(reporter, rtProxy->maxWindowRectangles(caps) == expectedMaxWindowRects);
51     REPORTER_ASSERT(reporter, rtProxy->numSamples() == numSamples);
52 
53     GrSurfaceProxy::UniqueID idBefore = rtProxy->uniqueID();
54     bool preinstantiated = rtProxy->isInstantiated();
55     REPORTER_ASSERT(reporter, rtProxy->instantiate(provider));
56     GrRenderTarget* rt = rtProxy->peekRenderTarget();
57 
58     REPORTER_ASSERT(reporter, rtProxy->uniqueID() == idBefore);
59     // Deferred resources should always have a different ID from their instantiated rendertarget
60     if (preinstantiated) {
61         REPORTER_ASSERT(reporter, rtProxy->uniqueID().asUInt() == rt->uniqueID().asUInt());
62     } else {
63         REPORTER_ASSERT(reporter, rtProxy->uniqueID().asUInt() != rt->uniqueID().asUInt());
64     }
65 
66     if (SkBackingFit::kExact == fit) {
67         REPORTER_ASSERT(reporter, rt->width() == rtProxy->width());
68         REPORTER_ASSERT(reporter, rt->height() == rtProxy->height());
69     } else {
70         REPORTER_ASSERT(reporter, rt->width() >= rtProxy->width());
71         REPORTER_ASSERT(reporter, rt->height() >= rtProxy->height());
72     }
73     REPORTER_ASSERT(reporter, rt->config() == rtProxy->config());
74 
75     REPORTER_ASSERT(reporter, rt->numSamples() == rtProxy->numSamples());
76     REPORTER_ASSERT(reporter, rt->surfacePriv().flags() == rtProxy->testingOnly_getFlags());
77 }
78 
check_texture(skiatest::Reporter * reporter,GrResourceProvider * provider,GrTextureProxy * texProxy,SkBackingFit fit)79 static void check_texture(skiatest::Reporter* reporter,
80                           GrResourceProvider* provider,
81                           GrTextureProxy* texProxy,
82                           SkBackingFit fit) {
83     GrSurfaceProxy::UniqueID idBefore = texProxy->uniqueID();
84 
85     bool preinstantiated = texProxy->isInstantiated();
86     REPORTER_ASSERT(reporter, texProxy->instantiate(provider));
87     GrTexture* tex = texProxy->peekTexture();
88 
89     REPORTER_ASSERT(reporter, texProxy->uniqueID() == idBefore);
90     // Deferred resources should always have a different ID from their instantiated texture
91     if (preinstantiated) {
92         REPORTER_ASSERT(reporter, texProxy->uniqueID().asUInt() == tex->uniqueID().asUInt());
93     } else {
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()->priv().proxyProvider();
110     GrResourceProvider* resourceProvider = ctxInfo.grContext()->priv().resourceProvider();
111     const GrCaps& caps = *ctxInfo.grContext()->priv().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 ct : { GrColorType::kAlpha_8, GrColorType::kBGR_565,
118                              GrColorType::kRGBA_8888, GrColorType::kRGBA_1010102 } ) {
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 
123                             auto config = GrColorTypeToPixelConfig(ct);
124                             SkASSERT(kUnknown_GrPixelConfig != config);
125 
126                             GrSurfaceDesc desc;
127                             desc.fWidth = widthHeight;
128                             desc.fHeight = widthHeight;
129                             desc.fConfig = config;
130 
131                             auto format = caps.getDefaultBackendFormat(ct, GrRenderable::kYes);
132                             if (!format.isValid()) {
133                                 continue;
134                             }
135 
136                             // Renderable
137                             {
138                                 sk_sp<GrTexture> tex;
139                                 if (SkBackingFit::kApprox == fit) {
140                                     tex = resourceProvider->createApproxTexture(
141                                             desc, format, GrRenderable::kYes, numSamples,
142                                             GrProtected::kNo,
143                                             GrResourceProvider::Flags::kNoPendingIO);
144                                 } else {
145                                     tex = resourceProvider->createTexture(
146                                             desc, format, GrRenderable::kYes, numSamples, budgeted,
147                                             GrProtected::kNo,
148                                             GrResourceProvider::Flags::kNoPendingIO);
149                                 }
150 
151                                 sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(
152                                         format, desc, GrRenderable::kYes, numSamples, origin, fit,
153                                         budgeted, GrProtected::kNo);
154                                 REPORTER_ASSERT(reporter, SkToBool(tex) == SkToBool(proxy));
155                                 if (proxy) {
156                                     REPORTER_ASSERT(reporter, proxy->asRenderTargetProxy());
157                                     // This forces the proxy to compute and cache its
158                                     // pre-instantiation size guess. Later, when it is actually
159                                     // instantiated, it checks that the instantiated size is <= to
160                                     // the pre-computation. If the proxy never computed its
161                                     // pre-instantiation size then the check is skipped.
162                                     proxy->gpuMemorySize();
163 
164                                     check_surface(reporter, proxy.get(), origin,
165                                                   widthHeight, widthHeight, config, budgeted);
166                                     int supportedSamples =
167                                             caps.getRenderTargetSampleCount(numSamples, format);
168                                     check_rendertarget(reporter, caps, resourceProvider,
169                                                        proxy->asRenderTargetProxy(),
170                                                        supportedSamples,
171                                                        fit, caps.maxWindowRectangles());
172                                 }
173                             }
174 
175                             // Not renderable
176                             {
177                                 sk_sp<GrTexture> tex;
178                                 if (SkBackingFit::kApprox == fit) {
179                                     tex = resourceProvider->createApproxTexture(
180                                             desc, format, GrRenderable::kNo, numSamples,
181                                             GrProtected::kNo,
182                                             GrResourceProvider::Flags::kNoPendingIO);
183                                 } else {
184                                     tex = resourceProvider->createTexture(
185                                             desc, format, GrRenderable::kNo, numSamples, budgeted,
186                                             GrProtected::kNo,
187                                             GrResourceProvider::Flags::kNoPendingIO);
188                                 }
189 
190                                 sk_sp<GrTextureProxy> proxy(proxyProvider->createProxy(
191                                         format, desc, GrRenderable::kNo, numSamples, origin, fit,
192                                         budgeted, GrProtected::kNo));
193                                 REPORTER_ASSERT(reporter, SkToBool(tex) == SkToBool(proxy));
194                                 if (proxy) {
195                                     // This forces the proxy to compute and cache its
196                                     // pre-instantiation size guess. Later, when it is actually
197                                     // instantiated, it checks that the instantiated size is <= to
198                                     // the pre-computation. If the proxy never computed its
199                                     // pre-instantiation size then the check is skipped.
200                                     proxy->gpuMemorySize();
201 
202                                     check_surface(reporter, proxy.get(), origin,
203                                                   widthHeight, widthHeight, config, budgeted);
204                                     check_texture(reporter, resourceProvider,
205                                                   proxy->asTextureProxy(), fit);
206                                 }
207                             }
208 
209                             attempt++;
210                         }
211                     }
212                 }
213             }
214         }
215     }
216 }
217 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest,reporter,ctxInfo)218 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) {
219     GrProxyProvider* proxyProvider = ctxInfo.grContext()->priv().proxyProvider();
220     GrContext* context = ctxInfo.grContext();
221     GrResourceProvider* resourceProvider = context->priv().resourceProvider();
222     GrGpu* gpu = context->priv().getGpu();
223     const GrCaps& caps = *context->priv().caps();
224 
225     static const int kWidthHeight = 100;
226 
227     for (auto origin : { kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin }) {
228         for (auto colorType : { kAlpha_8_SkColorType, kRGBA_8888_SkColorType,
229                                 kRGBA_1010102_SkColorType }) {
230             GrColorType grColorType = SkColorTypeToGrColorType(colorType);
231             GrPixelConfig config = GrColorTypeToPixelConfig(grColorType);
232             SkASSERT(kUnknown_GrPixelConfig != config);
233 
234             // External on-screen render target.
235             // Tests wrapBackendRenderTarget with a GrBackendRenderTarget
236             // Our test-only function that creates a backend render target doesn't currently support
237             // sample counts :(.
238             if (ctxInfo.grContext()->colorTypeSupportedAsSurface(colorType)) {
239                 GrBackendRenderTarget backendRT = gpu->createTestingOnlyBackendRenderTarget(
240                         kWidthHeight, kWidthHeight, grColorType);
241                 sk_sp<GrSurfaceProxy> sProxy(
242                         proxyProvider->wrapBackendRenderTarget(backendRT, grColorType,
243                                                                origin, nullptr, nullptr));
244                 check_surface(reporter, sProxy.get(), origin, kWidthHeight, kWidthHeight,
245                               config, SkBudgeted::kNo);
246                 static constexpr int kExpectedNumSamples = 1;
247                 check_rendertarget(reporter, caps, resourceProvider, sProxy->asRenderTargetProxy(),
248                                    kExpectedNumSamples, SkBackingFit::kExact,
249                                    caps.maxWindowRectangles());
250                 gpu->deleteTestingOnlyBackendRenderTarget(backendRT);
251             }
252 
253             for (auto numSamples : {1, 4}) {
254                 auto beFormat = caps.getDefaultBackendFormat(grColorType, GrRenderable::kYes);
255                 int supportedNumSamples = caps.getRenderTargetSampleCount(numSamples, beFormat);
256                 if (!supportedNumSamples) {
257                     continue;
258                 }
259 
260                 // Test wrapping FBO 0 (with made up properties). This tests sample count and the
261                 // special case where FBO 0 doesn't support window rectangles.
262                 if (GrBackendApi::kOpenGL == ctxInfo.backend()) {
263                     GrGLFramebufferInfo fboInfo;
264                     fboInfo.fFBOID = 0;
265                     fboInfo.fFormat = GrGLFormatToEnum(beFormat.asGLFormat());
266                     SkASSERT(fboInfo.fFormat);
267                     static constexpr int kStencilBits = 8;
268                     GrBackendRenderTarget backendRT(kWidthHeight, kWidthHeight, numSamples,
269                                                     kStencilBits, fboInfo);
270                     sk_sp<GrSurfaceProxy> sProxy(
271                             proxyProvider->wrapBackendRenderTarget(backendRT, grColorType,
272                                                                    origin, nullptr, nullptr));
273                     check_surface(reporter, sProxy.get(), origin,
274                                   kWidthHeight, kWidthHeight,
275                                   config, SkBudgeted::kNo);
276                     check_rendertarget(reporter, caps, resourceProvider,
277                                        sProxy->asRenderTargetProxy(),
278                                        supportedNumSamples, SkBackingFit::kExact, 0);
279                 }
280 
281                 // Tests wrapBackendRenderTarget with a GrBackendTexture
282                 {
283                     GrBackendTexture backendTex =
284                             context->createBackendTexture(kWidthHeight, kWidthHeight,
285                                                           colorType,
286                                                           SkColors::kTransparent,
287                                                           GrMipMapped::kNo,
288                                                           GrRenderable::kYes,
289                                                           GrProtected::kNo);
290                     sk_sp<GrSurfaceProxy> sProxy = proxyProvider->wrapBackendTextureAsRenderTarget(
291                             backendTex, grColorType, origin, supportedNumSamples);
292                     if (!sProxy) {
293                         context->deleteBackendTexture(backendTex);
294                         continue;  // This can fail on Mesa
295                     }
296 
297                     check_surface(reporter, sProxy.get(), origin,
298                                   kWidthHeight, kWidthHeight,
299                                   config, SkBudgeted::kNo);
300                     check_rendertarget(reporter, caps, resourceProvider,
301                                        sProxy->asRenderTargetProxy(),
302                                        supportedNumSamples, SkBackingFit::kExact,
303                                        caps.maxWindowRectangles());
304 
305                     context->deleteBackendTexture(backendTex);
306                 }
307 
308                 // Tests wrapBackendTexture that is only renderable
309                 {
310                     GrBackendTexture backendTex =
311                             context->createBackendTexture(kWidthHeight, kWidthHeight,
312                                                           colorType,
313                                                           SkColors::kTransparent,
314                                                           GrMipMapped::kNo,
315                                                           GrRenderable::kYes,
316                                                           GrProtected::kNo);
317 
318                     sk_sp<GrSurfaceProxy> sProxy = proxyProvider->wrapRenderableBackendTexture(
319                             backendTex, origin, supportedNumSamples,
320                             grColorType, kBorrow_GrWrapOwnership,
321                             GrWrapCacheable::kNo, nullptr, nullptr);
322                     if (!sProxy) {
323                         context->deleteBackendTexture(backendTex);
324                         continue;  // This can fail on Mesa
325                     }
326 
327                     check_surface(reporter, sProxy.get(), origin,
328                                   kWidthHeight, kWidthHeight,
329                                   config, SkBudgeted::kNo);
330                     check_rendertarget(reporter, caps, resourceProvider,
331                                        sProxy->asRenderTargetProxy(),
332                                        supportedNumSamples, SkBackingFit::kExact,
333                                        caps.maxWindowRectangles());
334 
335                     context->deleteBackendTexture(backendTex);
336                 }
337 
338                 // Tests wrapBackendTexture that is only textureable
339                 {
340                     // Internal offscreen texture
341                     GrBackendTexture backendTex =
342                             context->createBackendTexture(kWidthHeight, kWidthHeight,
343                                                           colorType,
344                                                           SkColors::kTransparent,
345                                                           GrMipMapped::kNo,
346                                                           GrRenderable::kNo,
347                                                           GrProtected::kNo);
348 
349                     sk_sp<GrSurfaceProxy> sProxy = proxyProvider->wrapBackendTexture(
350                             backendTex, grColorType, origin, kBorrow_GrWrapOwnership,
351                             GrWrapCacheable::kNo, kRead_GrIOType);
352                     if (!sProxy) {
353                         context->deleteBackendTexture(backendTex);
354                         continue;
355                     }
356 
357                     check_surface(reporter, sProxy.get(), origin,
358                                   kWidthHeight, kWidthHeight,
359                                   config, SkBudgeted::kNo);
360                     check_texture(reporter, resourceProvider, sProxy->asTextureProxy(),
361                                   SkBackingFit::kExact);
362 
363                     context->deleteBackendTexture(backendTex);
364                 }
365             }
366         }
367     }
368 }
369 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ZeroSizedProxyTest,reporter,ctxInfo)370 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ZeroSizedProxyTest, reporter, ctxInfo) {
371     GrContext* context = ctxInfo.grContext();
372     GrProxyProvider* provider = context->priv().proxyProvider();
373 
374     for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
375         for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
376             for (int width : { 0, 100 }) {
377                 for (int height : { 0, 100}) {
378                     if (width && height) {
379                         continue; // not zero-sized
380                     }
381 
382                     GrSurfaceDesc desc;
383                     desc.fWidth = width;
384                     desc.fHeight = height;
385                     desc.fConfig = kRGBA_8888_GrPixelConfig;
386 
387                     const GrBackendFormat format =
388                             context->priv().caps()->getDefaultBackendFormat(
389                                 GrColorType::kRGBA_8888,
390                                 renderable);
391 
392                     sk_sp<GrTextureProxy> proxy = provider->createProxy(
393                             format, desc, renderable, 1, kBottomLeft_GrSurfaceOrigin, fit,
394                             SkBudgeted::kNo, GrProtected::kNo);
395                     REPORTER_ASSERT(reporter, !proxy);
396                 }
397             }
398         }
399     }
400 }
401