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