• 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 #include "GrRenderTargetPriv.h"
14 #include "GrRenderTargetProxy.h"
15 #include "GrResourceProvider.h"
16 #include "GrSurfaceProxy.h"
17 #include "GrTextureProxy.h"
18 
19 // 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,const GrGpuResource::UniqueID & uniqueID,SkBudgeted budgeted)20 static void check_surface(skiatest::Reporter* reporter,
21                           GrSurfaceProxy* proxy,
22                           GrSurfaceOrigin origin,
23                           int width, int height,
24                           GrPixelConfig config,
25                           const GrGpuResource::UniqueID& uniqueID,
26                           SkBudgeted budgeted) {
27     REPORTER_ASSERT(reporter, proxy->origin() == origin);
28     REPORTER_ASSERT(reporter, proxy->width() == width);
29     REPORTER_ASSERT(reporter, proxy->height() == height);
30     REPORTER_ASSERT(reporter, proxy->config() == config);
31     if (!uniqueID.isInvalid()) {
32         REPORTER_ASSERT(reporter, proxy->uniqueID().asUInt() == uniqueID.asUInt());
33     } else {
34         REPORTER_ASSERT(reporter, !proxy->uniqueID().isInvalid());
35     }
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     GrRenderTarget* rt = rtProxy->instantiate(provider);
52     REPORTER_ASSERT(reporter, rt);
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     REPORTER_ASSERT(reporter, rt->origin() == rtProxy->origin());
64     if (SkBackingFit::kExact == fit) {
65         REPORTER_ASSERT(reporter, rt->width() == rtProxy->width());
66         REPORTER_ASSERT(reporter, rt->height() == rtProxy->height());
67     } else {
68         REPORTER_ASSERT(reporter, rt->width() >= rtProxy->width());
69         REPORTER_ASSERT(reporter, rt->height() >= rtProxy->height());
70     }
71     REPORTER_ASSERT(reporter, rt->config() == rtProxy->config());
72 
73     REPORTER_ASSERT(reporter, rt->isUnifiedMultisampled() == rtProxy->isUnifiedMultisampled());
74     REPORTER_ASSERT(reporter, rt->isStencilBufferMultisampled() ==
75                               rtProxy->isStencilBufferMultisampled());
76     REPORTER_ASSERT(reporter, rt->numColorSamples() == rtProxy->numColorSamples());
77     REPORTER_ASSERT(reporter, rt->numStencilSamples() == rtProxy->numStencilSamples());
78     REPORTER_ASSERT(reporter, rt->isMixedSampled() == rtProxy->isMixedSampled());
79     REPORTER_ASSERT(reporter, rt->renderTargetPriv().flags() == rtProxy->testingOnly_getFlags());
80 }
81 
check_texture(skiatest::Reporter * reporter,GrResourceProvider * provider,GrTextureProxy * texProxy,SkBackingFit fit,bool wasWrapped)82 static void check_texture(skiatest::Reporter* reporter,
83                           GrResourceProvider* provider,
84                           GrTextureProxy* texProxy,
85                           SkBackingFit fit,
86                           bool wasWrapped) {
87     GrSurfaceProxy::UniqueID idBefore = texProxy->uniqueID();
88     GrTexture* tex = texProxy->instantiate(provider);
89     REPORTER_ASSERT(reporter, tex);
90 
91     REPORTER_ASSERT(reporter, texProxy->uniqueID() == idBefore);
92     if (wasWrapped) {
93         // Wrapped resources share their uniqueID with the wrapping TextureProxy
94         REPORTER_ASSERT(reporter, texProxy->uniqueID().asUInt() == tex->uniqueID().asUInt());
95     } else {
96         // Deferred resources should always have a different ID from their instantiated texture
97         REPORTER_ASSERT(reporter, texProxy->uniqueID().asUInt() != tex->uniqueID().asUInt());
98     }
99 
100     REPORTER_ASSERT(reporter, tex->origin() == texProxy->origin());
101     if (SkBackingFit::kExact == fit) {
102         REPORTER_ASSERT(reporter, tex->width() == texProxy->width());
103         REPORTER_ASSERT(reporter, tex->height() == texProxy->height());
104     } else {
105         REPORTER_ASSERT(reporter, tex->width() >= texProxy->width());
106         REPORTER_ASSERT(reporter, tex->height() >= texProxy->height());
107     }
108     REPORTER_ASSERT(reporter, tex->config() == texProxy->config());
109 }
110 
111 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredProxyTest,reporter,ctxInfo)112 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredProxyTest, reporter, ctxInfo) {
113     GrResourceProvider* provider = ctxInfo.grContext()->resourceProvider();
114     const GrCaps& caps = *ctxInfo.grContext()->caps();
115 
116     const GrGpuResource::UniqueID kInvalidResourceID = GrGpuResource::UniqueID::InvalidID();
117 
118     int attempt = 0; // useful for debugging
119 
120     for (auto origin : { kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin }) {
121         for (auto widthHeight : { 100, 128, 1048576 }) {
122             for (auto config : { kAlpha_8_GrPixelConfig, kRGB_565_GrPixelConfig,
123                                  kETC1_GrPixelConfig, kRGBA_8888_GrPixelConfig }) {
124                 for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
125                     for (auto budgeted : { SkBudgeted::kYes, SkBudgeted::kNo }) {
126                         for (auto numSamples : { 0, 4, 16, 128 }) {
127                             GrSurfaceDesc desc;
128                             desc.fFlags = kRenderTarget_GrSurfaceFlag;
129                             desc.fOrigin = origin;
130                             desc.fWidth = widthHeight;
131                             desc.fHeight = widthHeight;
132                             desc.fConfig = config;
133                             desc.fSampleCnt = numSamples;
134 
135                             {
136                                 sk_sp<GrTexture> tex;
137                                 if (SkBackingFit::kApprox == fit) {
138                                     tex.reset(provider->createApproxTexture(desc, 0));
139                                 } else {
140                                     tex.reset(provider->createTexture(desc, budgeted));
141                                 }
142 
143                                 sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(
144                                                                                 provider, desc,
145                                                                                 fit, budgeted));
146                                 REPORTER_ASSERT(reporter, SkToBool(tex) == SkToBool(proxy));
147                                 if (proxy) {
148                                     REPORTER_ASSERT(reporter, proxy->asRenderTargetProxy());
149                                     // This forces the proxy to compute and cache its
150                                     // pre-instantiation size guess. Later, when it is actually
151                                     // instantiated, it checks that the instantiated size is <= to
152                                     // the pre-computation. If the proxy never computed its
153                                     // pre-instantiation size then the check is skipped.
154                                     proxy->gpuMemorySize();
155 
156                                     check_surface(reporter, proxy.get(), origin,
157                                                   widthHeight, widthHeight, config,
158                                                   kInvalidResourceID, budgeted);
159                                     check_rendertarget(reporter, caps, provider,
160                                                        proxy->asRenderTargetProxy(),
161                                                        SkTMin(numSamples, caps.maxSampleCount()),
162                                                        fit, caps.maxWindowRectangles(), false);
163                                 }
164                             }
165 
166                             desc.fFlags = kNone_GrSurfaceFlags;
167 
168                             {
169                                 sk_sp<GrTexture> tex;
170                                 if (SkBackingFit::kApprox == fit) {
171                                     tex.reset(provider->createApproxTexture(desc, 0));
172                                 } else {
173                                     tex.reset(provider->createTexture(desc, budgeted));
174                                 }
175 
176                                 sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(provider,
177                                                                                          desc,
178                                                                                          fit,
179                                                                                          budgeted));
180                                 REPORTER_ASSERT(reporter, SkToBool(tex) == SkToBool(proxy));
181                                 if (proxy) {
182                                     // This forces the proxy to compute and cache its pre-instantiation
183                                     // size guess. Later, when it is actually instantiated, it checks
184                                     // that the instantiated size is <= to the pre-computation.
185                                     // If the proxy never computed its pre-instantiation size then the
186                                     // check is skipped.
187                                     proxy->gpuMemorySize();
188 
189                                     check_surface(reporter, proxy.get(), origin,
190                                                   widthHeight, widthHeight, config,
191                                                   kInvalidResourceID, budgeted);
192                                     check_texture(reporter, provider, proxy->asTextureProxy(),
193                                                   fit, false);
194                                 }
195                             }
196 
197                             attempt++;
198                         }
199                     }
200                 }
201             }
202         }
203     }
204 }
205 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest,reporter,ctxInfo)206 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) {
207     GrResourceProvider* provider = ctxInfo.grContext()->resourceProvider();
208     const GrCaps& caps = *ctxInfo.grContext()->caps();
209 
210     static const int kWidthHeight = 100;
211 
212     for (auto origin : { kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin }) {
213         for (auto config : { kAlpha_8_GrPixelConfig, kRGBA_8888_GrPixelConfig }) {
214             for (auto budgeted : { SkBudgeted::kYes, SkBudgeted::kNo }) {
215                 for (auto numSamples: { 0, 4}) {
216                     bool renderable = caps.isConfigRenderable(config, numSamples > 0);
217 
218                     GrSurfaceDesc desc;
219                     desc.fOrigin = origin;
220                     desc.fWidth = kWidthHeight;
221                     desc.fHeight = kWidthHeight;
222                     desc.fConfig = config;
223                     desc.fSampleCnt = numSamples;
224 
225                     // External on-screen render target.
226                     if (renderable && kOpenGL_GrBackend == ctxInfo.backend()) {
227                         GrBackendRenderTargetDesc backendDesc;
228                         backendDesc.fWidth = kWidthHeight;
229                         backendDesc.fHeight = kWidthHeight;
230                         backendDesc.fConfig = config;
231                         backendDesc.fOrigin = origin;
232                         backendDesc.fSampleCnt = numSamples;
233                         backendDesc.fStencilBits = 8;
234                         backendDesc.fRenderTargetHandle = 0;
235 
236                         sk_sp<GrRenderTarget> defaultFBO(
237                             provider->wrapBackendRenderTarget(backendDesc));
238 
239                         sk_sp<GrSurfaceProxy> sProxy(GrSurfaceProxy::MakeWrapped(defaultFBO));
240                         check_surface(reporter, sProxy.get(), origin,
241                                       kWidthHeight, kWidthHeight, config,
242                                       defaultFBO->uniqueID(), SkBudgeted::kNo);
243                         check_rendertarget(reporter, caps, provider, sProxy->asRenderTargetProxy(),
244                                            numSamples, SkBackingFit::kExact, 0, true);
245                     }
246 
247                     sk_sp<GrTexture> tex;
248 
249                     // Internal offscreen render target.
250                     if (renderable) {
251                         desc.fFlags = kRenderTarget_GrSurfaceFlag;
252                         tex.reset(provider->createTexture(desc, budgeted));
253                         sk_sp<GrRenderTarget> rt(sk_ref_sp(tex->asRenderTarget()));
254 
255                         sk_sp<GrSurfaceProxy> sProxy(GrSurfaceProxy::MakeWrapped(rt));
256                         check_surface(reporter, sProxy.get(), origin,
257                                       kWidthHeight, kWidthHeight, config,
258                                       rt->uniqueID(), budgeted);
259                         check_rendertarget(reporter, caps, provider, sProxy->asRenderTargetProxy(),
260                                            numSamples, SkBackingFit::kExact,
261                                            caps.maxWindowRectangles(), true);
262                     }
263 
264                     if (!tex) {
265                         SkASSERT(kNone_GrSurfaceFlags == desc.fFlags );
266                         desc.fSampleCnt = 0;
267                         tex.reset(provider->createTexture(desc, budgeted));
268                     }
269 
270                     sk_sp<GrSurfaceProxy> sProxy(GrSurfaceProxy::MakeWrapped(tex));
271                     check_surface(reporter, sProxy.get(), origin,
272                                   kWidthHeight, kWidthHeight, config, tex->uniqueID(), budgeted);
273                     check_texture(reporter, provider, sProxy->asTextureProxy(),
274                                   SkBackingFit::kExact, true);
275                 }
276             }
277         }
278     }
279 }
280 
281 #endif
282