xref: /aosp_15_r20/external/skia/tests/ProxyTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/ganesh/GrBackendSurface.h"
16 #include "include/gpu/ganesh/GrDirectContext.h"
17 #include "include/gpu/ganesh/GrTypes.h"
18 #include "include/gpu/ganesh/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             if (!backendRT.isValid()) {
288                 continue;
289             }
290             sk_sp<GrSurfaceProxy> sProxy(
291                     proxyProvider->wrapBackendRenderTarget(backendRT, nullptr));
292             check_surface(reporter, sProxy.get(), kWidthHeight, kWidthHeight, Budgeted::kNo);
293             static constexpr int kExpectedNumSamples = 1;
294             check_rendertarget(reporter, caps, resourceProvider, sProxy->asRenderTargetProxy(),
295                                kExpectedNumSamples, SkBackingFit::kExact,
296                                caps.maxWindowRectangles());
297             gpu->deleteTestingOnlyBackendRenderTarget(backendRT);
298         }
299 
300         for (auto numSamples : {1, 4}) {
301             auto beFormat = caps.getDefaultBackendFormat(grColorType, GrRenderable::kYes);
302             int supportedNumSamples = caps.getRenderTargetSampleCount(numSamples, beFormat);
303             if (!supportedNumSamples) {
304                 continue;
305             }
306 
307 #ifdef SK_GL
308             // Test wrapping FBO 0 (with made up properties). This tests sample count and the
309             // special case where FBO 0 doesn't support window rectangles.
310             if (GrBackendApi::kOpenGL == ctxInfo.backend()) {
311                 GrGLFramebufferInfo fboInfo;
312                 fboInfo.fFBOID = 0;
313                 fboInfo.fFormat = GrBackendFormats::AsGLFormatEnum(beFormat);
314                 fboInfo.fProtected = isProtected;
315                 SkASSERT(fboInfo.fFormat);
316                 static constexpr int kStencilBits = 8;
317                 GrBackendRenderTarget backendRT = GrBackendRenderTargets::MakeGL(
318                         kWidthHeight, kWidthHeight, numSamples, kStencilBits, fboInfo);
319                 sk_sp<GrSurfaceProxy> sProxy(
320                         proxyProvider->wrapBackendRenderTarget(backendRT, nullptr));
321                 check_surface(
322                         reporter, sProxy.get(), kWidthHeight, kWidthHeight, Budgeted::kNo);
323                 check_rendertarget(reporter, caps, resourceProvider, sProxy->asRenderTargetProxy(),
324                                    supportedNumSamples, SkBackingFit::kExact, 0);
325             }
326 #endif
327 
328             // Tests wrapBackendTexture that is only renderable
329             {
330                 auto mbet =
331                         sk_gpu_test::ManagedBackendTexture::MakeWithoutData(direct,
332                                                                             kWidthHeight,
333                                                                             kWidthHeight,
334                                                                             colorType,
335                                                                             Mipmapped::kNo,
336                                                                             GrRenderable::kYes,
337                                                                             isProtected);
338                 if (!mbet) {
339                     ERRORF(reporter,
340                            "Could not create renderable backend texture of color type %d",
341                            colorType);
342                     continue;
343                 }
344                 sk_sp<GrSurfaceProxy> sProxy = proxyProvider->wrapRenderableBackendTexture(
345                         mbet->texture(), supportedNumSamples, kBorrow_GrWrapOwnership,
346                         GrWrapCacheable::kNo, nullptr);
347                 if (!sProxy) {
348                     ERRORF(reporter, "wrapRenderableBackendTexture failed");
349                     continue;
350                 }
351 
352                 check_surface(
353                         reporter, sProxy.get(), kWidthHeight, kWidthHeight, Budgeted::kNo);
354                 check_rendertarget(reporter, caps, resourceProvider, sProxy->asRenderTargetProxy(),
355                                    supportedNumSamples, SkBackingFit::kExact,
356                                    caps.maxWindowRectangles());
357             }
358 
359             {
360                 // Tests wrapBackendTexture that is only textureable
361                 auto mbet =
362                         sk_gpu_test::ManagedBackendTexture::MakeWithoutData(direct,
363                                                                             kWidthHeight,
364                                                                             kWidthHeight,
365                                                                             colorType,
366                                                                             Mipmapped::kNo,
367                                                                             GrRenderable::kNo,
368                                                                             isProtected);
369                 if (!mbet) {
370                     ERRORF(reporter,
371                            "Could not create non-renderable backend texture of color type %d",
372                            colorType);
373                     continue;
374                 }
375                 sk_sp<GrSurfaceProxy> sProxy = proxyProvider->wrapBackendTexture(
376                         mbet->texture(), kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
377                         kRead_GrIOType, mbet->refCountedCallback());
378                 if (!sProxy) {
379                     ERRORF(reporter, "wrapBackendTexture failed");
380                     continue;
381                 }
382 
383                 check_surface(
384                         reporter, sProxy.get(), kWidthHeight, kWidthHeight, Budgeted::kNo);
385                 check_texture(reporter, resourceProvider, sProxy->asTextureProxy(),
386                               SkBackingFit::kExact);
387             }
388         }
389     }
390 }
391 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ZeroSizedProxyTest,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)392 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ZeroSizedProxyTest,
393                                        reporter,
394                                        ctxInfo,
395                                        CtsEnforcement::kApiLevel_T) {
396     auto direct = ctxInfo.directContext();
397     GrProxyProvider* provider = direct->priv().proxyProvider();
398 
399     for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
400         for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
401             for (int width : { 0, 100 }) {
402                 for (int height : { 0, 100}) {
403                     if (width && height) {
404                         continue; // not zero-sized
405                     }
406 
407                     const GrBackendFormat format =
408                             direct->priv().caps()->getDefaultBackendFormat(
409                                 GrColorType::kRGBA_8888,
410                                 renderable);
411 
412                     sk_sp<GrTextureProxy> proxy = provider->createProxy(format,
413                                                                         {width, height},
414                                                                         renderable,
415                                                                         1,
416                                                                         skgpu::Mipmapped::kNo,
417                                                                         fit,
418                                                                         skgpu::Budgeted::kNo,
419                                                                         GrProtected::kNo,
420                                                                         /*label=*/{});
421                     REPORTER_ASSERT(reporter, !proxy);
422                 }
423             }
424         }
425     }
426 }
427