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