blob: 18139dc643a46ca5823ab105015b8dd63520ecd0 [file] [log] [blame]
Robert Phillips7ffbcf92017-12-04 12:52:46 -05001/*
2 * Copyright 2017 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkBitmap.h"
9#include "include/core/SkCanvas.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040010#include "include/core/SkColor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkColorSpace.h"
Robert Phillips4d5594d2020-02-21 14:24:40 -050012#include "include/core/SkDeferredDisplayList.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkDeferredDisplayListRecorder.h"
14#include "include/core/SkImage.h"
15#include "include/core/SkImageInfo.h"
16#include "include/core/SkPaint.h"
17#include "include/core/SkPromiseImageTexture.h"
18#include "include/core/SkRect.h"
19#include "include/core/SkRefCnt.h"
20#include "include/core/SkSurface.h"
21#include "include/core/SkSurfaceCharacterization.h"
22#include "include/core/SkSurfaceProps.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040023#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "include/gpu/GrBackendSurface.h"
25#include "include/gpu/GrContext.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040026#include "include/gpu/GrContextThreadSafeProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "include/gpu/GrTypes.h"
28#include "include/gpu/gl/GrGLTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050029#include "include/private/GrTypesPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050030#include "src/core/SkDeferredDisplayListPriv.h"
31#include "src/gpu/GrCaps.h"
32#include "src/gpu/GrContextPriv.h"
33#include "src/gpu/GrGpu.h"
34#include "src/gpu/GrRenderTargetContext.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040035#include "src/gpu/GrRenderTargetProxy.h"
36#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050037#include "src/gpu/SkGpuDevice.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050038#include "src/gpu/gl/GrGLDefines.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040039#include "src/image/SkImage_GpuBase.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050040#include "src/image/SkSurface_Gpu.h"
41#include "tests/Test.h"
Robert Phillipsee5fd132019-05-07 13:29:22 -040042#include "tests/TestUtils.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050043#include "tools/gpu/GrContextFactory.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040044
45#include <initializer_list>
46#include <memory>
47#include <utility>
Robert Phillipsfc711a22018-02-13 17:03:00 -050048
Robert Phillips3cd54322019-07-10 09:28:59 -040049#ifdef SK_VULKAN
50#include "src/gpu/vk/GrVkCaps.h"
51#endif
52
Robert Phillips7ffbcf92017-12-04 12:52:46 -050053class SurfaceParameters {
54public:
Robert Phillips3cd54322019-07-10 09:28:59 -040055 static const int kNumParams = 12;
56 static const int kSampleCount = 5;
57 static const int kMipMipCount = 8;
58 static const int kFBO0Count = 9;
59 static const int kProtectedCount = 11;
Robert Phillips7ffbcf92017-12-04 12:52:46 -050060
Robert Phillips3cd54322019-07-10 09:28:59 -040061 SurfaceParameters(GrContext* context)
62 : fBackend(context->backend())
Robert Phillipsb45f47d2019-02-03 17:17:54 -050063 , fWidth(64)
Robert Phillips7ffbcf92017-12-04 12:52:46 -050064 , fHeight(64)
65 , fOrigin(kTopLeft_GrSurfaceOrigin)
66 , fColorType(kRGBA_8888_SkColorType)
67 , fColorSpace(SkColorSpace::MakeSRGB())
Brian Salomonbdecacf2018-02-02 20:32:49 -050068 , fSampleCount(1)
Robert Phillipse8fabb22018-02-04 14:33:21 -050069 , fSurfaceProps(0x0, kUnknown_SkPixelGeometry)
Robert Phillipsb45f47d2019-02-03 17:17:54 -050070 , fShouldCreateMipMaps(true)
71 , fUsesGLFBO0(false)
Robert Phillips3cd54322019-07-10 09:28:59 -040072 , fIsTextureable(true)
73 , fIsProtected(GrProtected::kNo) {
74#ifdef SK_VULKAN
75 if (GrBackendApi::kVulkan == context->backend()) {
76 const GrVkCaps* vkCaps = (const GrVkCaps*) context->priv().caps();
77
78 fIsProtected = GrProtected(vkCaps->supportsProtectedMemory());
79 }
80#endif
Robert Phillipse8fabb22018-02-04 14:33:21 -050081 }
Robert Phillips7ffbcf92017-12-04 12:52:46 -050082
83 int sampleCount() const { return fSampleCount; }
84
Robert Phillipsbe77a022018-04-03 17:17:05 -040085 void setColorType(SkColorType ct) { fColorType = ct; }
Robert Phillipsd8f79a22019-06-24 13:25:42 -040086 SkColorType colorType() const { return fColorType; }
Robert Phillipsbe77a022018-04-03 17:17:05 -040087 void setColorSpace(sk_sp<SkColorSpace> cs) { fColorSpace = std::move(cs); }
Robert Phillipsb45f47d2019-02-03 17:17:54 -050088 void setTextureable(bool isTextureable) { fIsTextureable = isTextureable; }
Brian Salomon4687bdd2019-05-09 16:28:04 -040089 void setShouldCreateMipMaps(bool shouldCreateMipMaps) {
90 fShouldCreateMipMaps = shouldCreateMipMaps;
91 }
Robert Phillipsbe77a022018-04-03 17:17:05 -040092
Robert Phillips7ffbcf92017-12-04 12:52:46 -050093 // Modify the SurfaceParameters in just one way
94 void modify(int i) {
95 switch (i) {
96 case 0:
97 fWidth = 63;
98 break;
99 case 1:
100 fHeight = 63;
101 break;
102 case 2:
103 fOrigin = kBottomLeft_GrSurfaceOrigin;
104 break;
105 case 3:
106 fColorType = kRGBA_F16_SkColorType;
107 break;
108 case 4:
Brian Osman37f99882018-08-09 10:26:57 -0400109 // This just needs to be a colorSpace different from that returned by MakeSRGB().
110 // In this case we just change the gamut.
Brian Osman82ebe042019-01-04 17:03:00 -0500111 fColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kAdobeRGB);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500112 break;
113 case kSampleCount:
114 fSampleCount = 4;
115 break;
116 case 6:
117 fSurfaceProps = SkSurfaceProps(0x0, kRGB_H_SkPixelGeometry);
118 break;
119 case 7:
120 fSurfaceProps = SkSurfaceProps(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
121 kUnknown_SkPixelGeometry);
122 break;
Robert Phillipse8fabb22018-02-04 14:33:21 -0500123 case 8:
124 fShouldCreateMipMaps = false;
125 break;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500126 case 9:
127 if (GrBackendApi::kOpenGL == fBackend) {
128 fUsesGLFBO0 = true;
Robert Phillipsc046ff02019-07-01 10:34:03 -0400129 fShouldCreateMipMaps = false; // needs to changed in tandem w/ textureability
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500130 fIsTextureable = false;
131 }
132 break;
133 case 10:
Robert Phillipsc046ff02019-07-01 10:34:03 -0400134 fShouldCreateMipMaps = false; // needs to changed in tandem w/ textureability
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500135 fIsTextureable = false;
136 break;
Robert Phillips3cd54322019-07-10 09:28:59 -0400137 case 11:
138 fIsProtected = GrProtected::kYes == fIsProtected ? GrProtected::kNo
139 : GrProtected::kYes;
140 break;
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500141 }
142 }
143
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400144 SkSurfaceCharacterization createCharacterization(GrContext* context) const {
Robert Phillipscf39f372019-09-03 10:29:20 -0400145 size_t maxResourceBytes = context->getResourceCacheLimit();
Robert Phillipsfc711a22018-02-13 17:03:00 -0500146
Robert Phillipsd470e1b2019-09-04 15:05:35 -0400147 if (!context->colorTypeSupportedAsSurface(fColorType)) {
148 return SkSurfaceCharacterization();
149 }
150
Robert Phillipsfc711a22018-02-13 17:03:00 -0500151 // Note that Ganesh doesn't make use of the SkImageInfo's alphaType
152 SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType,
153 kPremul_SkAlphaType, fColorSpace);
154
Robert Phillips0a15cc62019-07-30 12:49:10 -0400155 GrBackendFormat backendFormat = context->defaultBackendFormat(fColorType,
156 GrRenderable::kYes);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400157 if (!backendFormat.isValid()) {
158 return SkSurfaceCharacterization();
159 }
Robert Phillipsfc711a22018-02-13 17:03:00 -0500160
161 SkSurfaceCharacterization c = context->threadSafeProxy()->createCharacterization(
162 maxResourceBytes, ii, backendFormat, fSampleCount,
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500163 fOrigin, fSurfaceProps, fShouldCreateMipMaps,
Robert Phillips3cd54322019-07-10 09:28:59 -0400164 fUsesGLFBO0, fIsTextureable, fIsProtected);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400165 return c;
166 }
167
168 // Create a DDL whose characterization captures the current settings
169 std::unique_ptr<SkDeferredDisplayList> createDDL(GrContext* context) const {
170 SkSurfaceCharacterization c = this->createCharacterization(context);
Robert Phillipsfc711a22018-02-13 17:03:00 -0500171 SkAssertResult(c.isValid());
Robert Phillipse8fabb22018-02-04 14:33:21 -0500172
173 SkDeferredDisplayListRecorder r(c);
174 SkCanvas* canvas = r.getCanvas();
175 if (!canvas) {
176 return nullptr;
177 }
178
179 canvas->drawRect(SkRect::MakeXYWH(10, 10, 10, 10), SkPaint());
180 return r.detach();
181 }
182
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500183 // Create the surface with the current set of parameters
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500184 sk_sp<SkSurface> make(GrContext* context, GrBackendTexture* backend) const {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400185 const SkSurfaceCharacterization c = this->createCharacterization(context);
186
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500187 GrMipMapped mipmapped = !fIsTextureable
Robert Phillipsbe77a022018-04-03 17:17:05 -0400188 ? GrMipMapped::kNo
189 : GrMipMapped(fShouldCreateMipMaps);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500190
John Rosasco24cbdab2019-09-25 14:14:35 -0700191#ifdef SK_GL
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500192 if (fUsesGLFBO0) {
193 if (GrBackendApi::kOpenGL != context->backend()) {
194 return nullptr;
195 }
196
197 GrGLFramebufferInfo fboInfo;
198 fboInfo.fFBOID = 0;
199 fboInfo.fFormat = GR_GL_RGBA8;
200 static constexpr int kStencilBits = 8;
201 GrBackendRenderTarget backendRT(fWidth, fHeight, 1, kStencilBits, fboInfo);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500202
203 if (!backendRT.isValid()) {
204 return nullptr;
205 }
206
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400207 sk_sp<SkSurface> result = SkSurface::MakeFromBackendRenderTarget(context, backendRT,
208 fOrigin, fColorType,
209 fColorSpace,
210 &fSurfaceProps);
Robert Phillips9907e6e2019-06-25 14:47:04 -0400211 SkASSERT(result->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400212 return result;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500213 }
John Rosasco24cbdab2019-09-25 14:14:35 -0700214#endif
Greg Danielc1ad77c2020-05-06 11:40:03 -0400215 CreateBackendTexture(context, backend, fWidth, fHeight, fColorType,
216 SkColors::kTransparent, mipmapped, GrRenderable::kYes, fIsProtected);
Robert Phillips7c8af172019-07-08 15:55:24 -0400217 if (!backend->isValid()) {
Robert Phillipse8fabb22018-02-04 14:33:21 -0500218 return nullptr;
219 }
220
Robert Phillipsc046ff02019-07-01 10:34:03 -0400221 // Even if a characterization couldn't be constructed we want to soldier on to make
222 // sure that surface creation will/would've also failed
223 SkASSERT(!c.isValid() || c.isCompatible(*backend));
224
Robert Phillipsbe77a022018-04-03 17:17:05 -0400225 sk_sp<SkSurface> surface;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500226 if (!fIsTextureable) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400227 // Create a surface w/ the current parameters but make it non-textureable
228 surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
229 context, *backend, fOrigin, fSampleCount, fColorType,
230 fColorSpace, &fSurfaceProps);
231 } else {
232 surface = SkSurface::MakeFromBackendTexture(
233 context, *backend, fOrigin, fSampleCount, fColorType,
234 fColorSpace, &fSurfaceProps);
235 }
Robert Phillipse8fabb22018-02-04 14:33:21 -0500236
237 if (!surface) {
Robert Phillipsc046ff02019-07-01 10:34:03 -0400238 SkASSERT(!c.isValid());
Robert Phillips9b16f812019-05-17 10:01:21 -0400239 this->cleanUpBackEnd(context, *backend);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500240 return nullptr;
241 }
242
Robert Phillipsc046ff02019-07-01 10:34:03 -0400243 SkASSERT(c.isValid());
Robert Phillips9907e6e2019-06-25 14:47:04 -0400244 SkASSERT(surface->isCompatible(c));
Robert Phillipse8fabb22018-02-04 14:33:21 -0500245 return surface;
246 }
247
Brian Salomon26102cb2018-03-09 09:33:19 -0500248 void cleanUpBackEnd(GrContext* context, const GrBackendTexture& backend) const {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400249 context->deleteBackendTexture(backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500250 }
251
252private:
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500253 GrBackendApi fBackend;
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500254 int fWidth;
255 int fHeight;
256 GrSurfaceOrigin fOrigin;
257 SkColorType fColorType;
258 sk_sp<SkColorSpace> fColorSpace;
259 int fSampleCount;
260 SkSurfaceProps fSurfaceProps;
Robert Phillipse8fabb22018-02-04 14:33:21 -0500261 bool fShouldCreateMipMaps;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500262 bool fUsesGLFBO0;
263 bool fIsTextureable;
Robert Phillips3cd54322019-07-10 09:28:59 -0400264 GrProtected fIsProtected;
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500265};
266
Robert Phillipsc1267c62018-04-04 11:12:39 -0400267// Test out operator== && operator!=
268DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLOperatorEqTest, reporter, ctxInfo) {
269 GrContext* context = ctxInfo.grContext();
270
271 for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
Robert Phillips3cd54322019-07-10 09:28:59 -0400272 SurfaceParameters params1(context);
Robert Phillipsc1267c62018-04-04 11:12:39 -0400273 params1.modify(i);
274
275 SkSurfaceCharacterization char1 = params1.createCharacterization(context);
276 if (!char1.isValid()) {
277 continue; // can happen on some platforms (ChromeOS)
278 }
279
280 for (int j = 0; j < SurfaceParameters::kNumParams; ++j) {
Robert Phillips3cd54322019-07-10 09:28:59 -0400281 SurfaceParameters params2(context);
Robert Phillipsc1267c62018-04-04 11:12:39 -0400282 params2.modify(j);
283
284 SkSurfaceCharacterization char2 = params2.createCharacterization(context);
285 if (!char2.isValid()) {
286 continue; // can happen on some platforms (ChromeOS)
287 }
288
289 if (i == j) {
290 REPORTER_ASSERT(reporter, char1 == char2);
291 } else {
292 REPORTER_ASSERT(reporter, char1 != char2);
293 }
294
295 }
296 }
297
298 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400299 SurfaceParameters params(context);
Robert Phillipsc1267c62018-04-04 11:12:39 -0400300
301 SkSurfaceCharacterization valid = params.createCharacterization(context);
302 SkASSERT(valid.isValid());
303
304 SkSurfaceCharacterization inval1, inval2;
305 SkASSERT(!inval1.isValid() && !inval2.isValid());
306
307 REPORTER_ASSERT(reporter, inval1 != inval2);
308 REPORTER_ASSERT(reporter, valid != inval1);
309 REPORTER_ASSERT(reporter, inval1 != valid);
310 }
311}
312
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400313////////////////////////////////////////////////////////////////////////////////
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500314// This tests SkSurfaceCharacterization/SkSurface compatibility
Robert Phillips3cd54322019-07-10 09:28:59 -0400315void DDLSurfaceCharacterizationTestImpl(GrContext* context, skiatest::Reporter* reporter) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500316 GrGpu* gpu = context->priv().getGpu();
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400317 const GrCaps* caps = context->priv().caps();
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500318
Robert Phillips9e441ee2018-02-01 15:14:55 -0500319 // Create a bitmap that we can readback into
320 SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
321 kPremul_SkAlphaType);
322 SkBitmap bitmap;
323 bitmap.allocPixels(imageInfo);
324
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500325 std::unique_ptr<SkDeferredDisplayList> ddl;
326
327 // First, create a DDL using the stock SkSurface parameters
328 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400329 SurfaceParameters params(context);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500330
Robert Phillipse8fabb22018-02-04 14:33:21 -0500331 ddl = params.createDDL(context);
Robert Phillipsfc711a22018-02-13 17:03:00 -0500332 SkAssertResult(ddl);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500333
334 // The DDL should draw into an SkSurface created with the same parameters
Robert Phillipsbe77a022018-04-03 17:17:05 -0400335 GrBackendTexture backend;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500336 sk_sp<SkSurface> s = params.make(context, &backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500337 if (!s) {
338 return;
339 }
340
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500341 REPORTER_ASSERT(reporter, s->draw(ddl.get()));
Robert Phillips9e441ee2018-02-01 15:14:55 -0500342 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400343 context->flushAndSubmit();
Robert Phillipsbe77a022018-04-03 17:17:05 -0400344 gpu->testingOnly_flushGpuAndSync();
345 s = nullptr;
346 params.cleanUpBackEnd(context, backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500347 }
348
349 // Then, alter each parameter in turn and check that the DDL & surface are incompatible
350 for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
Robert Phillips3cd54322019-07-10 09:28:59 -0400351 SurfaceParameters params(context);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500352 params.modify(i);
353
Robert Phillips3cd54322019-07-10 09:28:59 -0400354 if (SurfaceParameters::kProtectedCount == i) {
355 if (context->backend() != GrBackendApi::kVulkan) {
356 // Only the Vulkan backend respects the protected parameter
357 continue;
358 }
359#ifdef SK_VULKAN
360 const GrVkCaps* vkCaps = (const GrVkCaps*) context->priv().caps();
361
362 // And, even then, only when it is a protected context
363 if (!vkCaps->supportsProtectedMemory()) {
364 continue;
365 }
366#endif
367 }
368
Robert Phillipsbe77a022018-04-03 17:17:05 -0400369 GrBackendTexture backend;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500370 sk_sp<SkSurface> s = params.make(context, &backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500371 if (!s) {
372 continue;
373 }
374
375 if (SurfaceParameters::kSampleCount == i) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400376 int supportedSampleCount = caps->getRenderTargetSampleCount(
Greg Daniel6fa62e22019-08-07 15:52:37 -0400377 params.sampleCount(), backend.getBackendFormat());
Brian Salomonbdecacf2018-02-02 20:32:49 -0500378 if (1 == supportedSampleCount) {
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500379 // If changing the sample count won't result in a different
380 // surface characterization, skip this step
Robert Phillipsbe77a022018-04-03 17:17:05 -0400381 s = nullptr;
382 params.cleanUpBackEnd(context, backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500383 continue;
384 }
385 }
386
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400387 if (SurfaceParameters::kMipMipCount == i && !caps->mipMapSupport()) {
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400388 // If changing the mipmap setting won't result in a different surface characterization,
389 // skip this step
Robert Phillipsbe77a022018-04-03 17:17:05 -0400390 s = nullptr;
391 params.cleanUpBackEnd(context, backend);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500392 continue;
393 }
394
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500395 if (SurfaceParameters::kFBO0Count == i && context->backend() != GrBackendApi::kOpenGL) {
396 // FBO0 only affects the surface characterization when using OpenGL
397 s = nullptr;
398 params.cleanUpBackEnd(context, backend);
399 continue;
400 }
401
Robert Phillipse8fabb22018-02-04 14:33:21 -0500402 REPORTER_ASSERT(reporter, !s->draw(ddl.get()),
403 "DDLSurfaceCharacterizationTest failed on parameter: %d\n", i);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400404
Greg Daniel0a2464f2020-05-14 15:45:44 -0400405 context->flushAndSubmit();
Robert Phillipsbe77a022018-04-03 17:17:05 -0400406 gpu->testingOnly_flushGpuAndSync();
407 s = nullptr;
408 params.cleanUpBackEnd(context, backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500409 }
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500410
411 // Next test the compatibility of resource cache parameters
412 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400413 const SurfaceParameters params(context);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400414 GrBackendTexture backend;
415
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500416 sk_sp<SkSurface> s = params.make(context, &backend);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500417
Robert Phillipscf39f372019-09-03 10:29:20 -0400418 size_t maxResourceBytes = context->getResourceCacheLimit();
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500419
Robert Phillipscf39f372019-09-03 10:29:20 -0400420 context->setResourceCacheLimit(maxResourceBytes/2);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500421 REPORTER_ASSERT(reporter, !s->draw(ddl.get()));
422
Robert Phillips9e441ee2018-02-01 15:14:55 -0500423 // DDL TODO: once proxies/ops can be de-instantiated we can re-enable these tests.
424 // For now, DDLs are drawn once.
425#if 0
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500426 // resource limits >= those at characterization time are accepted
427 context->setResourceCacheLimits(2*maxResourceCount, maxResourceBytes);
428 REPORTER_ASSERT(reporter, s->draw(ddl.get()));
Robert Phillips9e441ee2018-02-01 15:14:55 -0500429 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500430
431 context->setResourceCacheLimits(maxResourceCount, 2*maxResourceBytes);
432 REPORTER_ASSERT(reporter, s->draw(ddl.get()));
Robert Phillips9e441ee2018-02-01 15:14:55 -0500433 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500434
435 context->setResourceCacheLimits(maxResourceCount, maxResourceBytes);
436 REPORTER_ASSERT(reporter, s->draw(ddl.get()));
Robert Phillips9e441ee2018-02-01 15:14:55 -0500437 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
438#endif
Robert Phillipsbe77a022018-04-03 17:17:05 -0400439
Greg Daniel0a2464f2020-05-14 15:45:44 -0400440 context->flushAndSubmit();
Robert Phillipsbe77a022018-04-03 17:17:05 -0400441 gpu->testingOnly_flushGpuAndSync();
442 s = nullptr;
443 params.cleanUpBackEnd(context, backend);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500444 }
445
Robert Phillipse8fabb22018-02-04 14:33:21 -0500446 // Test that the textureability of the DDL characterization can block a DDL draw
447 {
448 GrBackendTexture backend;
Robert Phillips3cd54322019-07-10 09:28:59 -0400449 SurfaceParameters params(context);
Robert Phillipsc046ff02019-07-01 10:34:03 -0400450 params.setShouldCreateMipMaps(false);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500451 params.setTextureable(false);
452
453 sk_sp<SkSurface> s = params.make(context, &backend);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500454 if (s) {
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500455 REPORTER_ASSERT(reporter, !s->draw(ddl.get())); // bc the DDL was made w/ textureability
Robert Phillipse8fabb22018-02-04 14:33:21 -0500456
Greg Daniel0a2464f2020-05-14 15:45:44 -0400457 context->flushAndSubmit();
Robert Phillipsbe77a022018-04-03 17:17:05 -0400458 gpu->testingOnly_flushGpuAndSync();
Robert Phillipse8fabb22018-02-04 14:33:21 -0500459 s = nullptr;
Brian Salomon26102cb2018-03-09 09:33:19 -0500460 params.cleanUpBackEnd(context, backend);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500461 }
462 }
463
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500464 // Make sure non-GPU-backed surfaces fail characterization
465 {
466 SkImageInfo ii = SkImageInfo::MakeN32(64, 64, kOpaque_SkAlphaType);
467
468 sk_sp<SkSurface> rasterSurface = SkSurface::MakeRaster(ii);
469 SkSurfaceCharacterization c;
470 REPORTER_ASSERT(reporter, !rasterSurface->characterize(&c));
471 }
Robert Phillips94458ee2018-03-06 13:41:51 -0500472
473 // Exercise the createResized method
474 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400475 SurfaceParameters params(context);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400476 GrBackendTexture backend;
Robert Phillips94458ee2018-03-06 13:41:51 -0500477
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500478 sk_sp<SkSurface> s = params.make(context, &backend);
Robert Phillips94458ee2018-03-06 13:41:51 -0500479 if (!s) {
480 return;
481 }
482
483 SkSurfaceCharacterization char0;
484 SkAssertResult(s->characterize(&char0));
485
486 // Too small
487 SkSurfaceCharacterization char1 = char0.createResized(-1, -1);
488 REPORTER_ASSERT(reporter, !char1.isValid());
489
490 // Too large
491 SkSurfaceCharacterization char2 = char0.createResized(1000000, 32);
492 REPORTER_ASSERT(reporter, !char2.isValid());
493
494 // Just right
495 SkSurfaceCharacterization char3 = char0.createResized(32, 32);
496 REPORTER_ASSERT(reporter, char3.isValid());
497 REPORTER_ASSERT(reporter, 32 == char3.width());
498 REPORTER_ASSERT(reporter, 32 == char3.height());
Robert Phillipsbe77a022018-04-03 17:17:05 -0400499
500 s = nullptr;
501 params.cleanUpBackEnd(context, backend);
Robert Phillips94458ee2018-03-06 13:41:51 -0500502 }
Robert Phillipsa975ef32019-10-03 11:09:17 -0400503
504 // Exercise the createColorSpace method
505 {
506 SurfaceParameters params(context);
507 GrBackendTexture backend;
508
509 sk_sp<SkSurface> s = params.make(context, &backend);
510 if (!s) {
511 return;
512 }
513
514 SkSurfaceCharacterization char0;
515 SkAssertResult(s->characterize(&char0));
516
517 // The default params create an sRGB color space
518 REPORTER_ASSERT(reporter, char0.colorSpace()->isSRGB());
519 REPORTER_ASSERT(reporter, !char0.colorSpace()->gammaIsLinear());
520
521 {
522 sk_sp<SkColorSpace> newCS = SkColorSpace::MakeSRGBLinear();
523
524 SkSurfaceCharacterization char1 = char0.createColorSpace(std::move(newCS));
525 REPORTER_ASSERT(reporter, char1.isValid());
526 REPORTER_ASSERT(reporter, !char1.colorSpace()->isSRGB());
527 REPORTER_ASSERT(reporter, char1.colorSpace()->gammaIsLinear());
528 }
529
530 {
531 SkSurfaceCharacterization char2 = char0.createColorSpace(nullptr);
532 REPORTER_ASSERT(reporter, char2.isValid());
533 REPORTER_ASSERT(reporter, !char2.colorSpace());
534 }
535
536 {
537 sk_sp<SkColorSpace> newCS = SkColorSpace::MakeSRGBLinear();
538
539 SkSurfaceCharacterization invalid;
540 REPORTER_ASSERT(reporter, !invalid.isValid());
541 SkSurfaceCharacterization stillInvalid = invalid.createColorSpace(std::move(newCS));
542 REPORTER_ASSERT(reporter, !stillInvalid.isValid());
543 }
544
545 s = nullptr;
546 params.cleanUpBackEnd(context, backend);
547 }
Robert Phillipsb3c061a2020-02-13 13:24:47 -0500548
549 // Exercise the createBackendFormat method
550 {
551 SurfaceParameters params(context);
552 GrBackendTexture backend;
553
554 sk_sp<SkSurface> s = params.make(context, &backend);
555 if (!s) {
556 return;
557 }
558
559 SkSurfaceCharacterization char0;
560 SkAssertResult(s->characterize(&char0));
561
562 // The default params create a renderable RGBA8 surface
563 auto originalBackendFormat = context->defaultBackendFormat(kRGBA_8888_SkColorType,
564 GrRenderable::kYes);
565 REPORTER_ASSERT(reporter, originalBackendFormat.isValid());
566 REPORTER_ASSERT(reporter, char0.backendFormat() == originalBackendFormat);
567
568 auto newBackendFormat = context->defaultBackendFormat(kRGB_565_SkColorType,
569 GrRenderable::kYes);
570
571 if (newBackendFormat.isValid()) {
572 SkSurfaceCharacterization char1 = char0.createBackendFormat(kRGB_565_SkColorType,
573 newBackendFormat);
574 REPORTER_ASSERT(reporter, char1.isValid());
575 REPORTER_ASSERT(reporter, char1.backendFormat() == newBackendFormat);
576
577 SkSurfaceCharacterization invalid;
578 REPORTER_ASSERT(reporter, !invalid.isValid());
579 auto stillInvalid = invalid.createBackendFormat(kRGB_565_SkColorType,
580 newBackendFormat);
581 REPORTER_ASSERT(reporter, !stillInvalid.isValid());
582 }
583
584 s = nullptr;
585 params.cleanUpBackEnd(context, backend);
586 }
587
588 // Exercise the createFBO0 method
589 if (context->backend() == GrBackendApi::kOpenGL) {
590 SurfaceParameters params(context);
591 GrBackendTexture backend;
592
593 sk_sp<SkSurface> s = params.make(context, &backend);
594 if (!s) {
595 return;
596 }
597
598 SkSurfaceCharacterization char0;
599 SkAssertResult(s->characterize(&char0));
600
601 // The default params create a non-FBO0 surface
602 REPORTER_ASSERT(reporter, !char0.usesGLFBO0());
603
604 {
605 SkSurfaceCharacterization char1 = char0.createFBO0(true);
606 REPORTER_ASSERT(reporter, char1.isValid());
607 REPORTER_ASSERT(reporter, char1.usesGLFBO0());
608 }
609
610 {
611 SkSurfaceCharacterization invalid;
612 REPORTER_ASSERT(reporter, !invalid.isValid());
613 SkSurfaceCharacterization stillInvalid = invalid.createFBO0(true);
614 REPORTER_ASSERT(reporter, !stillInvalid.isValid());
615 }
616
617 s = nullptr;
618 params.cleanUpBackEnd(context, backend);
619 }
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500620}
621
Robert Phillips2dbcbe82020-03-05 11:16:39 -0500622#ifdef SK_GL
623
624// Test out the surface compatibility checks regarding FBO0-ness. This test constructs
625// two parallel arrays of characterizations and surfaces in the order:
626// FBO0 w/ MSAA, FBO0 w/o MSAA, not-FBO0 w/ MSAA, not-FBO0 w/o MSAA
627// and then tries all sixteen combinations to check the expected compatibility.
628// Note: this is a GL-only test
629DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(CharacterizationFBO0nessTest, reporter, ctxInfo) {
630 GrContext* context = ctxInfo.grContext();
631 const GrCaps* caps = context->priv().caps();
632 sk_sp<GrContextThreadSafeProxy> proxy = context->threadSafeProxy();
633 const size_t resourceCacheLimit = context->getResourceCacheLimit();
634
635 GrBackendFormat format = GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_2D);
636
637 int availableSamples = caps->getRenderTargetSampleCount(4, format);
638 if (availableSamples <= 1) {
639 // This context doesn't support MSAA for RGBA8
640 return;
641 }
642
643 SkImageInfo ii = SkImageInfo::Make({ 128, 128 }, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
644
645 static constexpr int kStencilBits = 8;
646 static constexpr bool kNotMipMapped = false;
647 static constexpr bool kNotTextureable = false;
648 const SkSurfaceProps surfaceProps(0x0, kRGB_H_SkPixelGeometry);
649
Robert Phillips1b1bd4e2020-03-05 13:21:12 -0500650 // Rows are characterizations and columns are surfaces
Robert Phillips2dbcbe82020-03-05 11:16:39 -0500651 static const bool kExpectedCompatibility[4][4] = {
Robert Phillips1b1bd4e2020-03-05 13:21:12 -0500652 // FBO0 & MSAA, FBO0 & not-MSAA, not-FBO0 & MSAA, not-FBO0 & not-MSAA
653/* FBO0 & MSAA */ { true, false, false, false },
654/* FBO0 & not-MSAA */ { false, true, false, true },
655/* not-FBO0 & MSAA */ { false, false, true, false },
656/* not-FBO0 & not- */ { false, false, false, true }
Robert Phillips2dbcbe82020-03-05 11:16:39 -0500657 };
658
659 SkSurfaceCharacterization characterizations[4];
660 sk_sp<SkSurface> surfaces[4];
661
662 int index = 0;
663 for (bool isFBO0 : { true, false }) {
664 for (int numSamples : { availableSamples, 1 }) {
665 characterizations[index] = proxy->createCharacterization(resourceCacheLimit,
666 ii, format, numSamples,
667 kTopLeft_GrSurfaceOrigin,
668 surfaceProps, kNotMipMapped,
669 isFBO0, kNotTextureable);
670 SkASSERT(characterizations[index].sampleCount() == numSamples);
671 SkASSERT(characterizations[index].usesGLFBO0() == isFBO0);
672
673 GrGLFramebufferInfo fboInfo{ isFBO0 ? 0 : (GrGLuint) 1, GR_GL_RGBA8 };
674 GrBackendRenderTarget backendRT(128, 128, numSamples, kStencilBits, fboInfo);
675 SkAssertResult(backendRT.isValid());
676
677 surfaces[index] = SkSurface::MakeFromBackendRenderTarget(context, backendRT,
678 kTopLeft_GrSurfaceOrigin,
679 kRGBA_8888_SkColorType,
680 nullptr, &surfaceProps);
681 ++index;
682 }
683 }
684
Robert Phillips1b1bd4e2020-03-05 13:21:12 -0500685 for (int c = 0; c < 4; ++c) {
686 for (int s = 0; s < 4; ++s) {
Robert Phillips2dbcbe82020-03-05 11:16:39 -0500687 REPORTER_ASSERT(reporter,
Robert Phillips1b1bd4e2020-03-05 13:21:12 -0500688 kExpectedCompatibility[c][s] ==
689 surfaces[s]->isCompatible(characterizations[c]));
Robert Phillips2dbcbe82020-03-05 11:16:39 -0500690 }
691 }
692}
693#endif
694
Robert Phillips3cd54322019-07-10 09:28:59 -0400695DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo) {
696 GrContext* context = ctxInfo.grContext();
697
698 DDLSurfaceCharacterizationTestImpl(context, reporter);
699}
700
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500701// Test that a DDL created w/o textureability can be replayed into both a textureable and
702// non-textureable destination. Note that DDLSurfaceCharacterizationTest tests that a
703// textureable DDL cannot be played into a non-textureable destination but can be replayed
704// into a textureable destination.
705DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLNonTextureabilityTest, reporter, ctxInfo) {
706 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500707 GrGpu* gpu = context->priv().getGpu();
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500708
709 // Create a bitmap that we can readback into
710 SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
711 kPremul_SkAlphaType);
712 SkBitmap bitmap;
713 bitmap.allocPixels(imageInfo);
714
715 for (bool textureability : { true, false }) {
716 std::unique_ptr<SkDeferredDisplayList> ddl;
717
Robert Phillipsc046ff02019-07-01 10:34:03 -0400718 // First, create a DDL w/o textureability (and thus no mipmaps). TODO: once we have
719 // reusable DDLs, move this outside of the loop.
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500720 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400721 SurfaceParameters params(context);
Robert Phillipsc046ff02019-07-01 10:34:03 -0400722 params.setShouldCreateMipMaps(false);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500723 params.setTextureable(false);
724
725 ddl = params.createDDL(context);
726 SkAssertResult(ddl);
727 }
728
729 // Then verify it can draw into either flavor of destination
Robert Phillips3cd54322019-07-10 09:28:59 -0400730 SurfaceParameters params(context);
Robert Phillipsc046ff02019-07-01 10:34:03 -0400731 params.setShouldCreateMipMaps(textureability);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500732 params.setTextureable(textureability);
733
734 GrBackendTexture backend;
735 sk_sp<SkSurface> s = params.make(context, &backend);
736 if (!s) {
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500737 continue;
738 }
739
740 REPORTER_ASSERT(reporter, s->draw(ddl.get()));
741 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400742 context->flushAndSubmit();
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500743 gpu->testingOnly_flushGpuAndSync();
744 s = nullptr;
745 params.cleanUpBackEnd(context, backend);
746 }
747
748}
749
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400750static void test_make_render_target(skiatest::Reporter* reporter,
751 GrContext* context,
752 const SurfaceParameters& params) {
753 {
754 const SkSurfaceCharacterization c = params.createCharacterization(context);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400755
Robert Phillipsbe77a022018-04-03 17:17:05 -0400756 if (!c.isValid()) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400757 GrBackendTexture backend;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500758 sk_sp<SkSurface> tmp = params.make(context, &backend);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400759
760 // If we couldn't characterize the surface we shouldn't be able to create it either
761 REPORTER_ASSERT(reporter, !tmp);
762 if (tmp) {
763 tmp = nullptr;
764 params.cleanUpBackEnd(context, backend);
765 }
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400766 return;
767 }
768 }
769
770 const SkSurfaceCharacterization c = params.createCharacterization(context);
771 GrBackendTexture backend;
772
773 {
774 sk_sp<SkSurface> s = params.make(context, &backend);
775 REPORTER_ASSERT(reporter, s);
776 if (!s) {
777 REPORTER_ASSERT(reporter, !c.isValid());
778 params.cleanUpBackEnd(context, backend);
779 return;
780 }
781
782 REPORTER_ASSERT(reporter, c.isValid());
Robert Phillipsc046ff02019-07-01 10:34:03 -0400783 REPORTER_ASSERT(reporter, c.isCompatible(backend));
Robert Phillips9907e6e2019-06-25 14:47:04 -0400784 REPORTER_ASSERT(reporter, s->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400785 // Note that we're leaving 'backend' live here
786 }
787
788 // Make an SkSurface from scratch
789 {
790 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, c, SkBudgeted::kYes);
791 REPORTER_ASSERT(reporter, s);
Robert Phillips9907e6e2019-06-25 14:47:04 -0400792 REPORTER_ASSERT(reporter, s->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400793 }
794
Robert Phillips02dc0302019-07-02 17:58:27 -0400795 // Make an SkSurface that wraps the existing backend texture
796 {
797 sk_sp<SkSurface> s = SkSurface::MakeFromBackendTexture(context, c, backend);
798 REPORTER_ASSERT(reporter, s);
799 REPORTER_ASSERT(reporter, s->isCompatible(c));
800 }
801
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400802 params.cleanUpBackEnd(context, backend);
803}
804
805////////////////////////////////////////////////////////////////////////////////
806// This tests the SkSurface::MakeRenderTarget variants that take an SkSurfaceCharacterization.
807// In particular, the SkSurface, backendTexture and SkSurfaceCharacterization
808// should always be compatible.
Robert Phillips3cd54322019-07-10 09:28:59 -0400809void DDLMakeRenderTargetTestImpl(GrContext* context, skiatest::Reporter* reporter) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400810 for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
811
812 if (SurfaceParameters::kFBO0Count == i) {
813 // MakeRenderTarget doesn't support FBO0
Robert Phillipsbe77a022018-04-03 17:17:05 -0400814 continue;
815 }
816
Robert Phillips3cd54322019-07-10 09:28:59 -0400817 if (SurfaceParameters::kProtectedCount == i) {
818 if (context->backend() != GrBackendApi::kVulkan) {
819 // Only the Vulkan backend respects the protected parameter
820 continue;
821 }
822#ifdef SK_VULKAN
823 const GrVkCaps* vkCaps = (const GrVkCaps*) context->priv().caps();
824
825 // And, even then, only when it is a protected context
826 if (!vkCaps->supportsProtectedMemory()) {
827 continue;
828 }
829#endif
830 }
831
832
833 SurfaceParameters params(context);
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400834 params.modify(i);
835
Brian Salomon4687bdd2019-05-09 16:28:04 -0400836 if (!context->priv().caps()->mipMapSupport()) {
837 params.setShouldCreateMipMaps(false);
838 }
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400839
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400840 test_make_render_target(reporter, context, params);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400841 }
842}
843
Robert Phillips3cd54322019-07-10 09:28:59 -0400844DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMakeRenderTargetTest, reporter, ctxInfo) {
845 GrContext* context = ctxInfo.grContext();
846
847 DDLMakeRenderTargetTestImpl(context, reporter);
848}
849
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400850////////////////////////////////////////////////////////////////////////////////
Greg Danielf2336e42018-01-23 16:38:14 -0500851static constexpr int kSize = 8;
852
853struct TextureReleaseChecker {
854 TextureReleaseChecker() : fReleaseCount(0) {}
855 int fReleaseCount;
856 static void Release(void* self) {
857 static_cast<TextureReleaseChecker*>(self)->fReleaseCount++;
858 }
859};
860
861enum class DDLStage { kMakeImage, kDrawImage, kDetach, kDrawDDL };
862
863// This tests the ability to create and use wrapped textures in a DDL world
864DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
865 GrContext* context = ctxInfo.grContext();
Robert Phillips9b16f812019-05-17 10:01:21 -0400866
Greg Danielc1ad77c2020-05-06 11:40:03 -0400867 GrBackendTexture backendTex;
868 CreateBackendTexture(context, &backendTex, kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400869 SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
Brian Salomonf7778972018-03-08 10:13:17 -0500870 if (!backendTex.isValid()) {
871 return;
Greg Danielf2336e42018-01-23 16:38:14 -0500872 }
Brian Salomonf7778972018-03-08 10:13:17 -0500873
Robert Phillips3cd54322019-07-10 09:28:59 -0400874 SurfaceParameters params(context);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400875 GrBackendTexture backend;
Brian Salomonf7778972018-03-08 10:13:17 -0500876
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500877 sk_sp<SkSurface> s = params.make(context, &backend);
Brian Salomonf7778972018-03-08 10:13:17 -0500878 if (!s) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400879 context->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500880 return;
881 }
882
883 SkSurfaceCharacterization c;
884 SkAssertResult(s->characterize(&c));
885
886 std::unique_ptr<SkDeferredDisplayListRecorder> recorder(new SkDeferredDisplayListRecorder(c));
887
888 SkCanvas* canvas = recorder->getCanvas();
889 if (!canvas) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400890 s = nullptr;
891 params.cleanUpBackEnd(context, backend);
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400892 context->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500893 return;
894 }
895
896 GrContext* deferredContext = canvas->getGrContext();
897 if (!deferredContext) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400898 s = nullptr;
899 params.cleanUpBackEnd(context, backend);
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400900 context->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500901 return;
902 }
903
904 // Wrapped Backend Textures are not supported in DDL
905 sk_sp<SkImage> image =
906 SkImage::MakeFromAdoptedTexture(deferredContext, backendTex, kTopLeft_GrSurfaceOrigin,
907 kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
908 REPORTER_ASSERT(reporter, !image);
909
910 TextureReleaseChecker releaseChecker;
911 image = SkImage::MakeFromTexture(deferredContext, backendTex, kTopLeft_GrSurfaceOrigin,
912 kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr,
913 TextureReleaseChecker::Release, &releaseChecker);
914 REPORTER_ASSERT(reporter, !image);
915
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400916 context->deleteBackendTexture(backendTex);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400917
918 s = nullptr;
919 params.cleanUpBackEnd(context, backend);
Greg Danielf2336e42018-01-23 16:38:14 -0500920}
921
Brian Salomon59ef8c32019-01-30 12:20:56 -0500922static sk_sp<SkPromiseImageTexture> dummy_fulfill_proc(void*) {
923 SkASSERT(0);
924 return nullptr;
925}
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400926static void dummy_release_proc(void*) { SkASSERT(0); }
Brian Salomon59ef8c32019-01-30 12:20:56 -0500927static void dummy_done_proc(void*) {}
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400928
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400929////////////////////////////////////////////////////////////////////////////////
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400930// Test out the behavior of an invalid DDLRecorder
931DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLInvalidRecorder, reporter, ctxInfo) {
932 GrContext* context = ctxInfo.grContext();
933
934 {
935 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
936 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
937
938 SkSurfaceCharacterization characterization;
939 SkAssertResult(s->characterize(&characterization));
940
941 // never calling getCanvas means the backing surface is never allocated
942 SkDeferredDisplayListRecorder recorder(characterization);
943 }
944
945 {
946 SkSurfaceCharacterization invalid;
947
948 SkDeferredDisplayListRecorder recorder(invalid);
949
950 const SkSurfaceCharacterization c = recorder.characterization();
951 REPORTER_ASSERT(reporter, !c.isValid());
952 REPORTER_ASSERT(reporter, !recorder.getCanvas());
953 REPORTER_ASSERT(reporter, !recorder.detach());
954
Robert Phillips0a15cc62019-07-30 12:49:10 -0400955 GrBackendFormat format = context->defaultBackendFormat(kRGBA_8888_SkColorType,
956 GrRenderable::kNo);
957 SkASSERT(format.isValid());
Greg Daniel60ea40c2019-02-12 13:38:44 -0500958
Brian Salomonf55e8d52019-01-30 17:28:20 -0500959 sk_sp<SkImage> image = recorder.makePromiseTexture(
960 format, 32, 32, GrMipMapped::kNo,
961 kTopLeft_GrSurfaceOrigin,
962 kRGBA_8888_SkColorType,
963 kPremul_SkAlphaType, nullptr,
964 dummy_fulfill_proc,
965 dummy_release_proc,
966 dummy_done_proc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500967 nullptr,
968 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400969 REPORTER_ASSERT(reporter, !image);
970 }
971
972}
973
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400974////////////////////////////////////////////////////////////////////////////////
Robert Phillips874b5352018-03-16 08:48:24 -0400975// Ensure that flushing while DDL recording doesn't cause a crash
976DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLFlushWhileRecording, reporter, ctxInfo) {
977 GrContext* context = ctxInfo.grContext();
978
979 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
980 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
981
982 SkSurfaceCharacterization characterization;
983 SkAssertResult(s->characterize(&characterization));
984
985 SkDeferredDisplayListRecorder recorder(characterization);
986 SkCanvas* canvas = recorder.getCanvas();
987
Greg Daniel0a2464f2020-05-14 15:45:44 -0400988 canvas->getGrContext()->flushAndSubmit();
Robert Phillips874b5352018-03-16 08:48:24 -0400989}
Greg Danielf2336e42018-01-23 16:38:14 -0500990
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400991////////////////////////////////////////////////////////////////////////////////
Robert Phillipsee5fd132019-05-07 13:29:22 -0400992// Test that flushing a DDL via SkSurface::flush works
993
994struct FulfillInfo {
995 sk_sp<SkPromiseImageTexture> fTex;
996 bool fFulfilled = false;
997 bool fReleased = false;
998 bool fDone = false;
999};
1000
1001static sk_sp<SkPromiseImageTexture> tracking_fulfill_proc(void* context) {
1002 FulfillInfo* info = (FulfillInfo*) context;
1003 info->fFulfilled = true;
1004 return info->fTex;
1005}
1006
1007static void tracking_release_proc(void* context) {
1008 FulfillInfo* info = (FulfillInfo*) context;
1009 info->fReleased = true;
1010}
1011
1012static void tracking_done_proc(void* context) {
1013 FulfillInfo* info = (FulfillInfo*) context;
1014 info->fDone = true;
1015}
1016
1017DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSkSurfaceFlush, reporter, ctxInfo) {
1018 GrContext* context = ctxInfo.grContext();
1019
1020 SkImageInfo ii = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
1021 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
1022
1023 SkSurfaceCharacterization characterization;
1024 SkAssertResult(s->characterize(&characterization));
1025
1026 GrBackendTexture backendTexture;
1027
Robert Phillips0efc01d2019-11-06 17:19:30 +00001028 if (!CreateBackendTexture(context, &backendTexture, ii, SkColors::kCyan, GrMipMapped::kNo,
1029 GrRenderable::kNo)) {
Robert Phillipsee5fd132019-05-07 13:29:22 -04001030 REPORTER_ASSERT(reporter, false);
1031 return;
1032 }
1033
1034 FulfillInfo fulfillInfo;
1035 fulfillInfo.fTex = SkPromiseImageTexture::Make(backendTexture);
1036
1037 std::unique_ptr<SkDeferredDisplayList> ddl;
1038
1039 {
1040 SkDeferredDisplayListRecorder recorder(characterization);
1041
Robert Phillips0a15cc62019-07-30 12:49:10 -04001042 GrBackendFormat format = context->defaultBackendFormat(kRGBA_8888_SkColorType,
1043 GrRenderable::kNo);
1044 SkASSERT(format.isValid());
Robert Phillipsee5fd132019-05-07 13:29:22 -04001045
1046 sk_sp<SkImage> promiseImage = recorder.makePromiseTexture(
1047 format, 32, 32, GrMipMapped::kNo,
1048 kTopLeft_GrSurfaceOrigin,
1049 kRGBA_8888_SkColorType,
1050 kPremul_SkAlphaType, nullptr,
1051 tracking_fulfill_proc,
1052 tracking_release_proc,
1053 tracking_done_proc,
1054 &fulfillInfo,
1055 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
1056
1057 SkCanvas* canvas = recorder.getCanvas();
1058
1059 canvas->clear(SK_ColorRED);
1060 canvas->drawImage(promiseImage, 0, 0);
1061 ddl = recorder.detach();
1062 }
1063
Greg Daniel0a2464f2020-05-14 15:45:44 -04001064 context->flushAndSubmit();
Robert Phillips15c91422019-05-07 16:54:48 -04001065
Robert Phillipsee5fd132019-05-07 13:29:22 -04001066 s->draw(ddl.get());
1067
1068 GrFlushInfo flushInfo;
Robert Phillips8e49a692019-05-07 15:57:25 -04001069 s->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
Greg Daniel0a2464f2020-05-14 15:45:44 -04001070 context->submit();
Robert Phillipsee5fd132019-05-07 13:29:22 -04001071
1072 REPORTER_ASSERT(reporter, fulfillInfo.fFulfilled);
1073 REPORTER_ASSERT(reporter, fulfillInfo.fReleased);
1074
Robert Phillips8e49a692019-05-07 15:57:25 -04001075 if (GrBackendApi::kVulkan == context->backend() ||
1076 GrBackendApi::kMetal == context->backend()) {
Robert Phillips15c91422019-05-07 16:54:48 -04001077 // In order to receive the done callback with Vulkan we need to perform the equivalent
Robert Phillipsee5fd132019-05-07 13:29:22 -04001078 // of a glFinish
1079 GrFlushInfo flushInfoSyncCpu;
1080 flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
Robert Phillips8e49a692019-05-07 15:57:25 -04001081 s->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfoSyncCpu);
Greg Daniel0a2464f2020-05-14 15:45:44 -04001082 context->submit(true);
Robert Phillipsee5fd132019-05-07 13:29:22 -04001083 }
1084
1085 REPORTER_ASSERT(reporter, fulfillInfo.fDone);
1086
1087 REPORTER_ASSERT(reporter, fulfillInfo.fTex->unique());
1088 fulfillInfo.fTex.reset();
1089
Brian Salomon28a8f282019-10-24 20:07:39 -04001090 DeleteBackendTexture(context, backendTexture);
Robert Phillipsee5fd132019-05-07 13:29:22 -04001091}
1092
1093////////////////////////////////////////////////////////////////////////////////
Robert Phillipsf54883c2018-12-18 08:29:09 -05001094// Ensure that reusing a single DDLRecorder to create multiple DDLs works cleanly
1095DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMultipleDDLs, reporter, ctxInfo) {
1096 GrContext* context = ctxInfo.grContext();
1097
1098 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
1099 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
1100
1101 SkBitmap bitmap;
1102 bitmap.allocPixels(ii);
1103
1104 SkSurfaceCharacterization characterization;
1105 SkAssertResult(s->characterize(&characterization));
1106
1107 SkDeferredDisplayListRecorder recorder(characterization);
1108
1109 SkCanvas* canvas1 = recorder.getCanvas();
1110
1111 canvas1->clear(SK_ColorRED);
1112
1113 canvas1->save();
1114 canvas1->clipRect(SkRect::MakeXYWH(8, 8, 16, 16));
1115
1116 std::unique_ptr<SkDeferredDisplayList> ddl1 = recorder.detach();
1117
1118 SkCanvas* canvas2 = recorder.getCanvas();
1119
1120 SkPaint p;
1121 p.setColor(SK_ColorGREEN);
1122 canvas2->drawRect(SkRect::MakeWH(32, 32), p);
1123
1124 std::unique_ptr<SkDeferredDisplayList> ddl2 = recorder.detach();
1125
1126 REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData());
1127 REPORTER_ASSERT(reporter, ddl2->priv().lazyProxyData());
1128
1129 // The lazy proxy data being different ensures that the SkSurface, SkCanvas and backing-
1130 // lazy proxy are all different between the two DDLs
1131 REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData() != ddl2->priv().lazyProxyData());
1132
1133 s->draw(ddl1.get());
1134 s->draw(ddl2.get());
1135
1136 // Make sure the clipRect from DDL1 didn't percolate into DDL2
1137 s->readPixels(ii, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
1138 for (int y = 0; y < 32; ++y) {
1139 for (int x = 0; x < 32; ++x) {
1140 REPORTER_ASSERT(reporter, bitmap.getColor(x, y) == SK_ColorGREEN);
1141 if (bitmap.getColor(x, y) != SK_ColorGREEN) {
1142 return; // we only really need to report the error once
1143 }
1144 }
1145 }
1146}
1147
John Rosascoa9b348f2019-11-08 13:18:15 -08001148#ifdef SK_GL
Robert Phillipsf54883c2018-12-18 08:29:09 -05001149////////////////////////////////////////////////////////////////////////////////
Robert Phillipsabf7b762018-03-21 12:13:37 -04001150// Check that the texture-specific flags (i.e., for external & rectangle textures) work
1151// for promise images. As such, this is a GL-only test.
1152DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLTextureFlagsTest, reporter, ctxInfo) {
1153 GrContext* context = ctxInfo.grContext();
1154
1155 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
1156 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
1157
1158 SkSurfaceCharacterization characterization;
1159 SkAssertResult(s->characterize(&characterization));
1160
1161 SkDeferredDisplayListRecorder recorder(characterization);
1162
1163 for (GrGLenum target : { GR_GL_TEXTURE_EXTERNAL, GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_2D } ) {
Greg Daniel09c94002018-06-08 22:11:51 +00001164 for (auto mipMapped : { GrMipMapped::kNo, GrMipMapped::kYes }) {
1165 GrBackendFormat format = GrBackendFormat::MakeGL(GR_GL_RGBA8, target);
Robert Phillipsabf7b762018-03-21 12:13:37 -04001166
Brian Salomonf55e8d52019-01-30 17:28:20 -05001167 sk_sp<SkImage> image = recorder.makePromiseTexture(
1168 format, 32, 32, mipMapped,
1169 kTopLeft_GrSurfaceOrigin,
1170 kRGBA_8888_SkColorType,
1171 kPremul_SkAlphaType, nullptr,
1172 dummy_fulfill_proc,
1173 dummy_release_proc,
1174 dummy_done_proc,
Brian Salomon0cc57542019-03-08 13:28:46 -05001175 nullptr,
1176 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
Greg Daniel09c94002018-06-08 22:11:51 +00001177 if (GR_GL_TEXTURE_2D != target && mipMapped == GrMipMapped::kYes) {
1178 REPORTER_ASSERT(reporter, !image);
1179 continue;
1180 }
1181 REPORTER_ASSERT(reporter, image);
Robert Phillipsabf7b762018-03-21 12:13:37 -04001182
Jim Van Verth21bd60d2018-10-12 15:00:20 -04001183 GrTextureProxy* backingProxy = ((SkImage_GpuBase*) image.get())->peekProxy();
Robert Phillipsabf7b762018-03-21 12:13:37 -04001184
Greg Daniel09c94002018-06-08 22:11:51 +00001185 REPORTER_ASSERT(reporter, backingProxy->mipMapped() == mipMapped);
1186 if (GR_GL_TEXTURE_2D == target) {
Brian Salomonfd98c2c2018-07-31 17:25:29 -04001187 REPORTER_ASSERT(reporter, !backingProxy->hasRestrictedSampling());
Greg Daniel09c94002018-06-08 22:11:51 +00001188 } else {
Brian Salomonfd98c2c2018-07-31 17:25:29 -04001189 REPORTER_ASSERT(reporter, backingProxy->hasRestrictedSampling());
Greg Daniel09c94002018-06-08 22:11:51 +00001190 }
Robert Phillipsabf7b762018-03-21 12:13:37 -04001191 }
1192 }
Robert Phillipsbe77a022018-04-03 17:17:05 -04001193}
John Rosascoa9b348f2019-11-08 13:18:15 -08001194#endif // SK_GL
Robert Phillipsbe77a022018-04-03 17:17:05 -04001195
1196////////////////////////////////////////////////////////////////////////////////
Robert Phillips646f6372018-09-25 09:31:10 -04001197// Test colorType and pixelConfig compatibility.
Robert Phillipsbe77a022018-04-03 17:17:05 -04001198DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLCompatibilityTest, reporter, ctxInfo) {
1199 GrContext* context = ctxInfo.grContext();
1200
1201 for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
1202 SkColorType colorType = static_cast<SkColorType>(ct);
1203
Robert Phillips3cd54322019-07-10 09:28:59 -04001204 SurfaceParameters params(context);
Greg Daniel60ea40c2019-02-12 13:38:44 -05001205 params.setColorType(colorType);
1206 params.setColorSpace(nullptr);
Robert Phillipsbe77a022018-04-03 17:17:05 -04001207
Brian Salomon4687bdd2019-05-09 16:28:04 -04001208 if (!context->priv().caps()->mipMapSupport()) {
1209 params.setShouldCreateMipMaps(false);
1210 }
Greg Daniel60ea40c2019-02-12 13:38:44 -05001211
Robert Phillipsd8f79a22019-06-24 13:25:42 -04001212 test_make_render_target(reporter, context, params);
Robert Phillipsbe77a022018-04-03 17:17:05 -04001213 }
Robert Phillipsabf7b762018-03-21 12:13:37 -04001214
1215}