• 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 "include/core/SkColorType.h"
11 #include "include/core/SkRefCnt.h"
12 #include "include/core/SkSize.h"
13 #include "include/core/SkTypes.h"
14 #include "include/gpu/GpuTypes.h"
15 #include "include/gpu/GrBackendSurface.h"
16 #include "include/gpu/GrDirectContext.h"
17 #include "include/gpu/GrTypes.h"
18 #include "include/gpu/gl/GrGLTypes.h"
19 #include "include/private/base/SkTo.h"
20 #include "include/private/gpu/ganesh/GrTypesPriv.h"
21 #include "src/gpu/RefCntedCallback.h"
22 #include "src/gpu/SkBackingFit.h"
23 #include "src/gpu/ganesh/GrCaps.h"
24 #include "src/gpu/ganesh/GrDirectContextPriv.h"
25 #include "src/gpu/ganesh/GrGpu.h"
26 #include "src/gpu/ganesh/GrProxyProvider.h"
27 #include "src/gpu/ganesh/GrRenderTarget.h"
28 #include "src/gpu/ganesh/GrRenderTargetProxy.h"
29 #include "src/gpu/ganesh/GrResourceProvider.h"
30 #include "src/gpu/ganesh/GrSurfaceProxy.h"
31 #include "src/gpu/ganesh/GrTexture.h"
32 #include "src/gpu/ganesh/GrTextureProxy.h"
33 #include "tests/CtsEnforcement.h"
34 #include "tests/Test.h"
35 #include "tools/gpu/ManagedBackendTexture.h"
36 
37 #if defined(SK_GL)
38 #include "include/gpu/ganesh/gl/GrGLBackendSurface.h"
39 #endif
40 
41 #include <initializer_list>
42 
43 struct GrContextOptions;
44 
45 // Check that the surface proxy's member vars are set as expected
check_surface(skiatest::Reporter * reporter,GrSurfaceProxy * proxy,int width,int height,skgpu::Budgeted budgeted)46 static void check_surface(skiatest::Reporter* reporter,
47                           GrSurfaceProxy* proxy,
48                           int width,
49                           int height,
50                           skgpu::Budgeted budgeted) {
51     REPORTER_ASSERT(reporter, proxy->width() == width);
52     REPORTER_ASSERT(reporter, proxy->height() == height);
53     REPORTER_ASSERT(reporter, !proxy->uniqueID().isInvalid());
54     REPORTER_ASSERT(reporter, proxy->isBudgeted() == budgeted);
55 }
56 
check_rendertarget(skiatest::Reporter * reporter,const GrCaps & caps,GrResourceProvider * provider,GrRenderTargetProxy * rtProxy,int numSamples,SkBackingFit fit,int expectedMaxWindowRects)57 static void check_rendertarget(skiatest::Reporter* reporter,
58                                const GrCaps& caps,
59                                GrResourceProvider* provider,
60                                GrRenderTargetProxy* rtProxy,
61                                int numSamples,
62                                SkBackingFit fit,
63                                int expectedMaxWindowRects) {
64     REPORTER_ASSERT(reporter, rtProxy->maxWindowRectangles(caps) == expectedMaxWindowRects);
65     REPORTER_ASSERT(reporter, rtProxy->numSamples() == numSamples);
66 
67     GrSurfaceProxy::UniqueID idBefore = rtProxy->uniqueID();
68     bool preinstantiated = rtProxy->isInstantiated();
69     REPORTER_ASSERT(reporter, rtProxy->instantiate(provider));
70     GrRenderTarget* rt = rtProxy->peekRenderTarget();
71 
72     REPORTER_ASSERT(reporter, rtProxy->uniqueID() == idBefore);
73     // Deferred resources should always have a different ID from their instantiated rendertarget
74     if (preinstantiated) {
75         REPORTER_ASSERT(reporter, rtProxy->uniqueID().asUInt() == rt->uniqueID().asUInt());
76     } else {
77         REPORTER_ASSERT(reporter, rtProxy->uniqueID().asUInt() != rt->uniqueID().asUInt());
78     }
79 
80     if (SkBackingFit::kExact == fit) {
81         REPORTER_ASSERT(reporter, rt->dimensions() == rtProxy->dimensions());
82     } else {
83         REPORTER_ASSERT(reporter, rt->width() >= rtProxy->width());
84         REPORTER_ASSERT(reporter, rt->height() >= rtProxy->height());
85     }
86     REPORTER_ASSERT(reporter, rt->backendFormat() == rtProxy->backendFormat());
87 
88     REPORTER_ASSERT(reporter, rt->numSamples() == rtProxy->numSamples());
89     REPORTER_ASSERT(reporter, rt->flags() == rtProxy->testingOnly_getFlags());
90 }
91 
check_texture(skiatest::Reporter * reporter,GrResourceProvider * provider,GrTextureProxy * texProxy,SkBackingFit fit)92 static void check_texture(skiatest::Reporter* reporter,
93                           GrResourceProvider* provider,
94                           GrTextureProxy* texProxy,
95                           SkBackingFit fit) {
96     GrSurfaceProxy::UniqueID idBefore = texProxy->uniqueID();
97 
98     bool preinstantiated = texProxy->isInstantiated();
99     // The instantiated texture should have these dimensions. If the fit is kExact, then
100     // 'backingStoreDimensions' reports the original WxH. If it is kApprox, make sure that
101     // the texture is that size and didn't reuse one of the kExact surfaces in the provider.
102     // This is important because upstream usage (e.g. SkImage) reports size based on the
103     // backingStoreDimensions and client code may rely on that if they are creating backend
104     // resources.
105     // NOTE: we store these before instantiating, since after instantiation backingStoreDimensions
106     // just returns the target's dimensions. In this instance, we want to ensure the target's
107     // dimensions are no different from the original approximate (or exact) dimensions.
108     SkISize expectedSize = texProxy->backingStoreDimensions();
109 
110     REPORTER_ASSERT(reporter, texProxy->instantiate(provider));
111     GrTexture* tex = texProxy->peekTexture();
112 
113     REPORTER_ASSERT(reporter, texProxy->uniqueID() == idBefore);
114     // Deferred resources should always have a different ID from their instantiated texture
115     if (preinstantiated) {
116         REPORTER_ASSERT(reporter, texProxy->uniqueID().asUInt() == tex->uniqueID().asUInt());
117     } else {
118         REPORTER_ASSERT(reporter, texProxy->uniqueID().asUInt() != tex->uniqueID().asUInt());
119     }
120 
121     REPORTER_ASSERT(reporter, tex->dimensions() == expectedSize);
122 
123     REPORTER_ASSERT(reporter, tex->backendFormat() == texProxy->backendFormat());
124 }
125 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DeferredProxyTest,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)126 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DeferredProxyTest,
127                                        reporter,
128                                        ctxInfo,
129                                        CtsEnforcement::kApiLevel_T) {
130     using namespace skgpu;
131 
132     auto direct = ctxInfo.directContext();
133     GrProxyProvider* proxyProvider = direct->priv().proxyProvider();
134     GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
135     const GrCaps& caps = *direct->priv().caps();
136 
137     Protected isProtected = Protected(caps.supportsProtectedContent());
138 
139     for (auto widthHeight : {100, 128, 1048576}) {
140         for (auto ct : {GrColorType::kAlpha_8, GrColorType::kBGR_565, GrColorType::kRGBA_8888,
141                         GrColorType::kRGBA_1010102}) {
142             for (auto fit : {SkBackingFit::kExact, SkBackingFit::kApprox}) {
143                 for (auto budgeted : { Budgeted::kYes, Budgeted::kNo }) {
144                     for (auto numSamples : {1, 4, 16, 128}) {
145                         SkISize dims = {widthHeight, widthHeight};
146 
147                         auto format = caps.getDefaultBackendFormat(ct, GrRenderable::kYes);
148                         if (!format.isValid()) {
149                             continue;
150                         }
151 
152                         // Renderable
153                         {
154                             sk_sp<GrTexture> tex;
155                             if (SkBackingFit::kApprox == fit) {
156                                 tex = resourceProvider->createApproxTexture(dims,
157                                                                             format,
158                                                                             GrTextureType::k2D,
159                                                                             GrRenderable::kYes,
160                                                                             numSamples,
161                                                                             isProtected,
162                                                                             /*label=*/{});
163                             } else {
164                                 tex = resourceProvider->createTexture(dims,
165                                                                       format,
166                                                                       GrTextureType::k2D,
167                                                                       GrRenderable::kYes,
168                                                                       numSamples,
169                                                                       Mipmapped::kNo,
170                                                                       budgeted,
171                                                                       isProtected,
172                                                                       /*label=*/{});
173                             }
174 
175                             sk_sp<GrTextureProxy> proxy =
176                                     proxyProvider->createProxy(format,
177                                                                dims,
178                                                                GrRenderable::kYes,
179                                                                numSamples,
180                                                                Mipmapped::kNo,
181                                                                fit,
182                                                                budgeted,
183                                                                isProtected,
184                                                                /*label=*/{});
185                             REPORTER_ASSERT(reporter, SkToBool(tex) == SkToBool(proxy));
186                             if (proxy) {
187                                 REPORTER_ASSERT(reporter, proxy->asRenderTargetProxy());
188                                 // This forces the proxy to compute and cache its
189                                 // pre-instantiation size guess. Later, when it is actually
190                                 // instantiated, it checks that the instantiated size is <= to
191                                 // the pre-computation. If the proxy never computed its
192                                 // pre-instantiation size then the check is skipped.
193                                 proxy->gpuMemorySize();
194 
195                                 check_surface(reporter, proxy.get(), widthHeight, widthHeight,
196                                               budgeted);
197                                 int supportedSamples =
198                                         caps.getRenderTargetSampleCount(numSamples, format);
199                                 check_rendertarget(reporter, caps, resourceProvider,
200                                                    proxy->asRenderTargetProxy(), supportedSamples,
201                                                    fit, caps.maxWindowRectangles());
202                             }
203                         }
204 
205                         // Not renderable
206                         {
207                             sk_sp<GrTexture> tex;
208                             if (SkBackingFit::kApprox == fit) {
209                                 tex = resourceProvider->createApproxTexture(dims,
210                                                                             format,
211                                                                             GrTextureType::k2D,
212                                                                             GrRenderable::kNo,
213                                                                             numSamples,
214                                                                             isProtected,
215                                                                             /*label=*/{});
216                             } else {
217                                 tex = resourceProvider->createTexture(dims,
218                                                                       format,
219                                                                       GrTextureType::k2D,
220                                                                       GrRenderable::kNo,
221                                                                       numSamples,
222                                                                       Mipmapped::kNo,
223                                                                       budgeted,
224                                                                       isProtected,
225                                                                       /*label=*/{});
226                             }
227 
228                             sk_sp<GrTextureProxy> proxy(
229                                     proxyProvider->createProxy(format,
230                                                                dims,
231                                                                GrRenderable::kNo,
232                                                                numSamples,
233                                                                Mipmapped::kNo,
234                                                                fit,
235                                                                budgeted,
236                                                                isProtected,
237                                                                /*label=*/{}));
238                             REPORTER_ASSERT(reporter, SkToBool(tex) == SkToBool(proxy));
239                             if (proxy) {
240                                 // This forces the proxy to compute and cache its
241                                 // pre-instantiation size guess. Later, when it is actually
242                                 // instantiated, it checks that the instantiated size is <= to
243                                 // the pre-computation. If the proxy never computed its
244                                 // pre-instantiation size then the check is skipped.
245                                 proxy->gpuMemorySize();
246 
247                                 check_surface(reporter, proxy.get(), widthHeight, widthHeight,
248                                               budgeted);
249                                 check_texture(reporter, resourceProvider, proxy->asTextureProxy(),
250                                               fit);
251                             }
252                         }
253                     }
254                 }
255             }
256         }
257     }
258 }
259 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)260 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest,
261                                        reporter,
262                                        ctxInfo,
263                                        CtsEnforcement::kApiLevel_T) {
264     using namespace skgpu;
265 
266     auto direct = ctxInfo.directContext();
267     GrProxyProvider* proxyProvider = direct->priv().proxyProvider();
268     GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
269     GrGpu* gpu = direct->priv().getGpu();
270     const GrCaps& caps = *direct->priv().caps();
271 
272     Protected isProtected = Protected(caps.supportsProtectedContent());
273 
274     static const int kWidthHeight = 100;
275 
276     for (auto colorType :
277          {kAlpha_8_SkColorType, kRGBA_8888_SkColorType, kRGBA_1010102_SkColorType}) {
278         GrColorType grColorType = SkColorTypeToGrColorType(colorType);
279 
280         // External on-screen render target.
281         // Tests wrapBackendRenderTarget with a GrBackendRenderTarget
282         // Our test-only function that creates a backend render target doesn't currently support
283         // sample counts :(.
284         if (direct->colorTypeSupportedAsSurface(colorType)) {
285             GrBackendRenderTarget backendRT = gpu->createTestingOnlyBackendRenderTarget(
286                     {kWidthHeight, kWidthHeight}, grColorType, /* sampleCount= */ 1, isProtected);
287             sk_sp<GrSurfaceProxy> sProxy(
288                     proxyProvider->wrapBackendRenderTarget(backendRT, nullptr));
289             check_surface(reporter, sProxy.get(), kWidthHeight, kWidthHeight, Budgeted::kNo);
290             static constexpr int kExpectedNumSamples = 1;
291             check_rendertarget(reporter, caps, resourceProvider, sProxy->asRenderTargetProxy(),
292                                kExpectedNumSamples, SkBackingFit::kExact,
293                                caps.maxWindowRectangles());
294             gpu->deleteTestingOnlyBackendRenderTarget(backendRT);
295         }
296 
297         for (auto numSamples : {1, 4}) {
298             auto beFormat = caps.getDefaultBackendFormat(grColorType, GrRenderable::kYes);
299             int supportedNumSamples = caps.getRenderTargetSampleCount(numSamples, beFormat);
300             if (!supportedNumSamples) {
301                 continue;
302             }
303 
304 #ifdef SK_GL
305             // Test wrapping FBO 0 (with made up properties). This tests sample count and the
306             // special case where FBO 0 doesn't support window rectangles.
307             if (GrBackendApi::kOpenGL == ctxInfo.backend()) {
308                 GrGLFramebufferInfo fboInfo;
309                 fboInfo.fFBOID = 0;
310                 fboInfo.fFormat = GrBackendFormats::AsGLFormatEnum(beFormat);
311                 fboInfo.fProtected = isProtected;
312                 SkASSERT(fboInfo.fFormat);
313                 static constexpr int kStencilBits = 8;
314                 GrBackendRenderTarget backendRT = GrBackendRenderTargets::MakeGL(
315                         kWidthHeight, kWidthHeight, numSamples, kStencilBits, fboInfo);
316                 sk_sp<GrSurfaceProxy> sProxy(
317                         proxyProvider->wrapBackendRenderTarget(backendRT, nullptr));
318                 check_surface(
319                         reporter, sProxy.get(), kWidthHeight, kWidthHeight, Budgeted::kNo);
320                 check_rendertarget(reporter, caps, resourceProvider, sProxy->asRenderTargetProxy(),
321                                    supportedNumSamples, SkBackingFit::kExact, 0);
322             }
323 #endif
324 
325             // Tests wrapBackendTexture that is only renderable
326             {
327                 auto mbet =
328                         sk_gpu_test::ManagedBackendTexture::MakeWithoutData(direct,
329                                                                             kWidthHeight,
330                                                                             kWidthHeight,
331                                                                             colorType,
332                                                                             Mipmapped::kNo,
333                                                                             GrRenderable::kYes,
334                                                                             isProtected);
335                 if (!mbet) {
336                     ERRORF(reporter,
337                            "Could not create renderable backend texture of color type %d",
338                            colorType);
339                     continue;
340                 }
341                 sk_sp<GrSurfaceProxy> sProxy = proxyProvider->wrapRenderableBackendTexture(
342                         mbet->texture(), supportedNumSamples, kBorrow_GrWrapOwnership,
343                         GrWrapCacheable::kNo, nullptr);
344                 if (!sProxy) {
345                     ERRORF(reporter, "wrapRenderableBackendTexture failed");
346                     continue;
347                 }
348 
349                 check_surface(
350                         reporter, sProxy.get(), kWidthHeight, kWidthHeight, Budgeted::kNo);
351                 check_rendertarget(reporter, caps, resourceProvider, sProxy->asRenderTargetProxy(),
352                                    supportedNumSamples, SkBackingFit::kExact,
353                                    caps.maxWindowRectangles());
354             }
355 
356             {
357                 // Tests wrapBackendTexture that is only textureable
358                 auto mbet =
359                         sk_gpu_test::ManagedBackendTexture::MakeWithoutData(direct,
360                                                                             kWidthHeight,
361                                                                             kWidthHeight,
362                                                                             colorType,
363                                                                             Mipmapped::kNo,
364                                                                             GrRenderable::kNo,
365                                                                             isProtected);
366                 if (!mbet) {
367                     ERRORF(reporter,
368                            "Could not create non-renderable backend texture of color type %d",
369                            colorType);
370                     continue;
371                 }
372                 sk_sp<GrSurfaceProxy> sProxy = proxyProvider->wrapBackendTexture(
373                         mbet->texture(), kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
374                         kRead_GrIOType, mbet->refCountedCallback());
375                 if (!sProxy) {
376                     ERRORF(reporter, "wrapBackendTexture failed");
377                     continue;
378                 }
379 
380                 check_surface(
381                         reporter, sProxy.get(), kWidthHeight, kWidthHeight, Budgeted::kNo);
382                 check_texture(reporter, resourceProvider, sProxy->asTextureProxy(),
383                               SkBackingFit::kExact);
384             }
385         }
386     }
387 }
388 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ZeroSizedProxyTest,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)389 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ZeroSizedProxyTest,
390                                        reporter,
391                                        ctxInfo,
392                                        CtsEnforcement::kApiLevel_T) {
393     auto direct = ctxInfo.directContext();
394     GrProxyProvider* provider = direct->priv().proxyProvider();
395 
396     for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
397         for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
398             for (int width : { 0, 100 }) {
399                 for (int height : { 0, 100}) {
400                     if (width && height) {
401                         continue; // not zero-sized
402                     }
403 
404                     const GrBackendFormat format =
405                             direct->priv().caps()->getDefaultBackendFormat(
406                                 GrColorType::kRGBA_8888,
407                                 renderable);
408 
409                     sk_sp<GrTextureProxy> proxy = provider->createProxy(format,
410                                                                         {width, height},
411                                                                         renderable,
412                                                                         1,
413                                                                         skgpu::Mipmapped::kNo,
414                                                                         fit,
415                                                                         skgpu::Budgeted::kNo,
416                                                                         GrProtected::kNo,
417                                                                         /*label=*/{});
418                     REPORTER_ASSERT(reporter, !proxy);
419                 }
420             }
421         }
422     }
423 }
424