blob: ec5d4730aed194691d9e7abb405b95f117924cb2 [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"
Ben Wagner9707a7e2019-05-06 17:17:19 -040025#include "include/gpu/GrContextThreadSafeProxy.h"
Robert Phillips6d344c32020-07-06 10:56:46 -040026#include "include/gpu/GrDirectContext.h"
Robert Phillipsc8ae4942020-07-20 10:56:01 -040027#include "include/gpu/GrRecordingContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#include "include/gpu/GrTypes.h"
29#include "include/gpu/gl/GrGLTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050030#include "include/private/GrTypesPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050031#include "src/core/SkDeferredDisplayListPriv.h"
32#include "src/gpu/GrCaps.h"
33#include "src/gpu/GrContextPriv.h"
34#include "src/gpu/GrGpu.h"
Robert Phillipsc8ae4942020-07-20 10:56:01 -040035#include "src/gpu/GrRecordingContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050036#include "src/gpu/GrRenderTargetContext.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040037#include "src/gpu/GrRenderTargetProxy.h"
38#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050039#include "src/gpu/SkGpuDevice.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050040#include "src/gpu/gl/GrGLDefines.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040041#include "src/image/SkImage_GpuBase.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050042#include "src/image/SkSurface_Gpu.h"
43#include "tests/Test.h"
Robert Phillipsee5fd132019-05-07 13:29:22 -040044#include "tests/TestUtils.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050045#include "tools/gpu/GrContextFactory.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040046
47#include <initializer_list>
48#include <memory>
49#include <utility>
Robert Phillipsfc711a22018-02-13 17:03:00 -050050
Robert Phillips3cd54322019-07-10 09:28:59 -040051#ifdef SK_VULKAN
52#include "src/gpu/vk/GrVkCaps.h"
53#endif
54
Robert Phillips7ffbcf92017-12-04 12:52:46 -050055class SurfaceParameters {
56public:
Robert Phillips3cd54322019-07-10 09:28:59 -040057 static const int kNumParams = 12;
58 static const int kSampleCount = 5;
59 static const int kMipMipCount = 8;
60 static const int kFBO0Count = 9;
61 static const int kProtectedCount = 11;
Robert Phillips7ffbcf92017-12-04 12:52:46 -050062
Robert Phillipsc8ae4942020-07-20 10:56:01 -040063 SurfaceParameters(GrRecordingContext* rContext)
64 : fBackend(rContext->backend())
Robert Phillipsb45f47d2019-02-03 17:17:54 -050065 , fWidth(64)
Robert Phillips7ffbcf92017-12-04 12:52:46 -050066 , fHeight(64)
67 , fOrigin(kTopLeft_GrSurfaceOrigin)
68 , fColorType(kRGBA_8888_SkColorType)
69 , fColorSpace(SkColorSpace::MakeSRGB())
Brian Salomonbdecacf2018-02-02 20:32:49 -050070 , fSampleCount(1)
Robert Phillipse8fabb22018-02-04 14:33:21 -050071 , fSurfaceProps(0x0, kUnknown_SkPixelGeometry)
Robert Phillipsb45f47d2019-02-03 17:17:54 -050072 , fShouldCreateMipMaps(true)
73 , fUsesGLFBO0(false)
Robert Phillips3cd54322019-07-10 09:28:59 -040074 , fIsTextureable(true)
Greg Daniel638b2e82020-08-27 14:29:00 -040075 , fIsProtected(GrProtected::kNo)
76 , fVkRTSupportsInputAttachment(false) {
Robert Phillips3cd54322019-07-10 09:28:59 -040077#ifdef SK_VULKAN
Robert Phillipsc8ae4942020-07-20 10:56:01 -040078 if (GrBackendApi::kVulkan == rContext->backend()) {
79 const GrVkCaps* vkCaps = (const GrVkCaps*) rContext->priv().caps();
Robert Phillips3cd54322019-07-10 09:28:59 -040080
81 fIsProtected = GrProtected(vkCaps->supportsProtectedMemory());
82 }
83#endif
Robert Phillipse8fabb22018-02-04 14:33:21 -050084 }
Robert Phillips7ffbcf92017-12-04 12:52:46 -050085
86 int sampleCount() const { return fSampleCount; }
87
Robert Phillipsbe77a022018-04-03 17:17:05 -040088 void setColorType(SkColorType ct) { fColorType = ct; }
Robert Phillipsd8f79a22019-06-24 13:25:42 -040089 SkColorType colorType() const { return fColorType; }
Robert Phillipsbe77a022018-04-03 17:17:05 -040090 void setColorSpace(sk_sp<SkColorSpace> cs) { fColorSpace = std::move(cs); }
Robert Phillipsb45f47d2019-02-03 17:17:54 -050091 void setTextureable(bool isTextureable) { fIsTextureable = isTextureable; }
Brian Salomon4687bdd2019-05-09 16:28:04 -040092 void setShouldCreateMipMaps(bool shouldCreateMipMaps) {
93 fShouldCreateMipMaps = shouldCreateMipMaps;
94 }
Greg Daniel638b2e82020-08-27 14:29:00 -040095 void setVkRTInputAttachmentSupport(bool inputSupport) {
96 fVkRTSupportsInputAttachment = inputSupport;
97 }
Robert Phillipsbe77a022018-04-03 17:17:05 -040098
Robert Phillips7ffbcf92017-12-04 12:52:46 -050099 // Modify the SurfaceParameters in just one way
100 void modify(int i) {
101 switch (i) {
102 case 0:
103 fWidth = 63;
104 break;
105 case 1:
106 fHeight = 63;
107 break;
108 case 2:
109 fOrigin = kBottomLeft_GrSurfaceOrigin;
110 break;
111 case 3:
112 fColorType = kRGBA_F16_SkColorType;
113 break;
114 case 4:
Brian Osman37f99882018-08-09 10:26:57 -0400115 // This just needs to be a colorSpace different from that returned by MakeSRGB().
116 // In this case we just change the gamut.
Brian Osman82ebe042019-01-04 17:03:00 -0500117 fColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kAdobeRGB);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500118 break;
119 case kSampleCount:
120 fSampleCount = 4;
121 break;
122 case 6:
123 fSurfaceProps = SkSurfaceProps(0x0, kRGB_H_SkPixelGeometry);
124 break;
125 case 7:
126 fSurfaceProps = SkSurfaceProps(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
127 kUnknown_SkPixelGeometry);
128 break;
Robert Phillipse8fabb22018-02-04 14:33:21 -0500129 case 8:
130 fShouldCreateMipMaps = false;
131 break;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500132 case 9:
133 if (GrBackendApi::kOpenGL == fBackend) {
134 fUsesGLFBO0 = true;
Robert Phillipsc046ff02019-07-01 10:34:03 -0400135 fShouldCreateMipMaps = false; // needs to changed in tandem w/ textureability
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500136 fIsTextureable = false;
137 }
138 break;
139 case 10:
Robert Phillipsc046ff02019-07-01 10:34:03 -0400140 fShouldCreateMipMaps = false; // needs to changed in tandem w/ textureability
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500141 fIsTextureable = false;
142 break;
Robert Phillips3cd54322019-07-10 09:28:59 -0400143 case 11:
144 fIsProtected = GrProtected::kYes == fIsProtected ? GrProtected::kNo
145 : GrProtected::kYes;
146 break;
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500147 }
148 }
149
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400150 SkSurfaceCharacterization createCharacterization(GrDirectContext* dContext) const {
151 size_t maxResourceBytes = dContext->getResourceCacheLimit();
Robert Phillipsfc711a22018-02-13 17:03:00 -0500152
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400153 if (!dContext->colorTypeSupportedAsSurface(fColorType)) {
Robert Phillipsd470e1b2019-09-04 15:05:35 -0400154 return SkSurfaceCharacterization();
155 }
156
Robert Phillipsfc711a22018-02-13 17:03:00 -0500157 // Note that Ganesh doesn't make use of the SkImageInfo's alphaType
158 SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType,
159 kPremul_SkAlphaType, fColorSpace);
160
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400161 GrBackendFormat backendFormat = dContext->defaultBackendFormat(fColorType,
162 GrRenderable::kYes);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400163 if (!backendFormat.isValid()) {
164 return SkSurfaceCharacterization();
165 }
Robert Phillipsfc711a22018-02-13 17:03:00 -0500166
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400167 SkSurfaceCharacterization c = dContext->threadSafeProxy()->createCharacterization(
Robert Phillipsfc711a22018-02-13 17:03:00 -0500168 maxResourceBytes, ii, backendFormat, fSampleCount,
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500169 fOrigin, fSurfaceProps, fShouldCreateMipMaps,
Greg Daniel638b2e82020-08-27 14:29:00 -0400170 fUsesGLFBO0, fIsTextureable, fIsProtected,
171 fVkRTSupportsInputAttachment);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400172 return c;
173 }
174
175 // Create a DDL whose characterization captures the current settings
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400176 sk_sp<SkDeferredDisplayList> createDDL(GrDirectContext* dContext) const {
177 SkSurfaceCharacterization c = this->createCharacterization(dContext);
Robert Phillipsfc711a22018-02-13 17:03:00 -0500178 SkAssertResult(c.isValid());
Robert Phillipse8fabb22018-02-04 14:33:21 -0500179
180 SkDeferredDisplayListRecorder r(c);
181 SkCanvas* canvas = r.getCanvas();
182 if (!canvas) {
183 return nullptr;
184 }
185
186 canvas->drawRect(SkRect::MakeXYWH(10, 10, 10, 10), SkPaint());
187 return r.detach();
188 }
189
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500190 // Create the surface with the current set of parameters
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400191 sk_sp<SkSurface> make(GrDirectContext* dContext, GrBackendTexture* backend) const {
192 const SkSurfaceCharacterization c = this->createCharacterization(dContext);
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400193
Brian Salomon7e67dca2020-07-21 09:27:25 -0400194 GrMipmapped mipmapped = !fIsTextureable
195 ? GrMipmapped::kNo
196 : GrMipmapped(fShouldCreateMipMaps);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500197
John Rosasco24cbdab2019-09-25 14:14:35 -0700198#ifdef SK_GL
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500199 if (fUsesGLFBO0) {
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400200 if (GrBackendApi::kOpenGL != dContext->backend()) {
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500201 return nullptr;
202 }
203
204 GrGLFramebufferInfo fboInfo;
205 fboInfo.fFBOID = 0;
206 fboInfo.fFormat = GR_GL_RGBA8;
207 static constexpr int kStencilBits = 8;
208 GrBackendRenderTarget backendRT(fWidth, fHeight, 1, kStencilBits, fboInfo);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500209
210 if (!backendRT.isValid()) {
211 return nullptr;
212 }
213
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400214 sk_sp<SkSurface> result = SkSurface::MakeFromBackendRenderTarget(dContext, backendRT,
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400215 fOrigin, fColorType,
216 fColorSpace,
217 &fSurfaceProps);
Robert Phillips9907e6e2019-06-25 14:47:04 -0400218 SkASSERT(result->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400219 return result;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500220 }
John Rosasco24cbdab2019-09-25 14:14:35 -0700221#endif
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400222 CreateBackendTexture(dContext, backend, fWidth, fHeight, fColorType,
Greg Danielc1ad77c2020-05-06 11:40:03 -0400223 SkColors::kTransparent, mipmapped, GrRenderable::kYes, fIsProtected);
Robert Phillips7c8af172019-07-08 15:55:24 -0400224 if (!backend->isValid()) {
Robert Phillipse8fabb22018-02-04 14:33:21 -0500225 return nullptr;
226 }
227
Robert Phillipsc046ff02019-07-01 10:34:03 -0400228 // Even if a characterization couldn't be constructed we want to soldier on to make
229 // sure that surface creation will/would've also failed
230 SkASSERT(!c.isValid() || c.isCompatible(*backend));
231
Robert Phillipsbe77a022018-04-03 17:17:05 -0400232 sk_sp<SkSurface> surface;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500233 if (!fIsTextureable) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400234 // Create a surface w/ the current parameters but make it non-textureable
235 surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400236 dContext, *backend, fOrigin, fSampleCount, fColorType,
Robert Phillipsbe77a022018-04-03 17:17:05 -0400237 fColorSpace, &fSurfaceProps);
238 } else {
239 surface = SkSurface::MakeFromBackendTexture(
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400240 dContext, *backend, fOrigin, fSampleCount, fColorType,
Robert Phillipsbe77a022018-04-03 17:17:05 -0400241 fColorSpace, &fSurfaceProps);
242 }
Robert Phillipse8fabb22018-02-04 14:33:21 -0500243
244 if (!surface) {
Robert Phillipsc046ff02019-07-01 10:34:03 -0400245 SkASSERT(!c.isValid());
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400246 this->cleanUpBackEnd(dContext, *backend);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500247 return nullptr;
248 }
249
Robert Phillipsc046ff02019-07-01 10:34:03 -0400250 SkASSERT(c.isValid());
Robert Phillips9907e6e2019-06-25 14:47:04 -0400251 SkASSERT(surface->isCompatible(c));
Robert Phillipse8fabb22018-02-04 14:33:21 -0500252 return surface;
253 }
254
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400255 void cleanUpBackEnd(GrDirectContext* dContext, const GrBackendTexture& backend) const {
256 dContext->deleteBackendTexture(backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500257 }
258
259private:
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500260 GrBackendApi fBackend;
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500261 int fWidth;
262 int fHeight;
263 GrSurfaceOrigin fOrigin;
264 SkColorType fColorType;
265 sk_sp<SkColorSpace> fColorSpace;
266 int fSampleCount;
267 SkSurfaceProps fSurfaceProps;
Robert Phillipse8fabb22018-02-04 14:33:21 -0500268 bool fShouldCreateMipMaps;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500269 bool fUsesGLFBO0;
270 bool fIsTextureable;
Robert Phillips3cd54322019-07-10 09:28:59 -0400271 GrProtected fIsProtected;
Greg Daniel638b2e82020-08-27 14:29:00 -0400272 bool fVkRTSupportsInputAttachment;
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500273};
274
Robert Phillipsc1267c62018-04-04 11:12:39 -0400275// Test out operator== && operator!=
276DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLOperatorEqTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400277 auto context = ctxInfo.directContext();
Robert Phillipsc1267c62018-04-04 11:12:39 -0400278
Brian Salomon69100f02020-07-21 10:49:25 -0400279 bool mipmapSupport = context->priv().caps()->mipmapSupport();
Robert Phillipsc1267c62018-04-04 11:12:39 -0400280 for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
Robert Phillips3cd54322019-07-10 09:28:59 -0400281 SurfaceParameters params1(context);
Robert Phillipsc1267c62018-04-04 11:12:39 -0400282 params1.modify(i);
283
284 SkSurfaceCharacterization char1 = params1.createCharacterization(context);
285 if (!char1.isValid()) {
286 continue; // can happen on some platforms (ChromeOS)
287 }
288
Brian Salomon69100f02020-07-21 10:49:25 -0400289 if (SurfaceParameters::kMipMipCount == i && !mipmapSupport) {
Stephen White33603fd2020-06-29 11:04:43 -0400290 // If changing the mipmap setting won't result in a different surface characterization,
291 // skip this step.
292 continue;
293 }
294
Robert Phillipsc1267c62018-04-04 11:12:39 -0400295 for (int j = 0; j < SurfaceParameters::kNumParams; ++j) {
Robert Phillips3cd54322019-07-10 09:28:59 -0400296 SurfaceParameters params2(context);
Robert Phillipsc1267c62018-04-04 11:12:39 -0400297 params2.modify(j);
298
299 SkSurfaceCharacterization char2 = params2.createCharacterization(context);
300 if (!char2.isValid()) {
301 continue; // can happen on some platforms (ChromeOS)
302 }
303
Brian Salomon69100f02020-07-21 10:49:25 -0400304 if (SurfaceParameters::kMipMipCount == j && !mipmapSupport) {
Stephen White33603fd2020-06-29 11:04:43 -0400305 // If changing the mipmap setting won't result in a different surface
306 // characterization, skip this step.
307 continue;
308 }
309
Robert Phillipsc1267c62018-04-04 11:12:39 -0400310 if (i == j) {
311 REPORTER_ASSERT(reporter, char1 == char2);
312 } else {
313 REPORTER_ASSERT(reporter, char1 != char2);
314 }
315
316 }
317 }
318
319 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400320 SurfaceParameters params(context);
Robert Phillipsc1267c62018-04-04 11:12:39 -0400321
322 SkSurfaceCharacterization valid = params.createCharacterization(context);
323 SkASSERT(valid.isValid());
324
325 SkSurfaceCharacterization inval1, inval2;
326 SkASSERT(!inval1.isValid() && !inval2.isValid());
327
328 REPORTER_ASSERT(reporter, inval1 != inval2);
329 REPORTER_ASSERT(reporter, valid != inval1);
330 REPORTER_ASSERT(reporter, inval1 != valid);
331 }
332}
333
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400334////////////////////////////////////////////////////////////////////////////////
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500335// This tests SkSurfaceCharacterization/SkSurface compatibility
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400336void DDLSurfaceCharacterizationTestImpl(GrDirectContext* dContext, skiatest::Reporter* reporter) {
337 GrGpu* gpu = dContext->priv().getGpu();
338 const GrCaps* caps = dContext->priv().caps();
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500339
Robert Phillips9e441ee2018-02-01 15:14:55 -0500340 // Create a bitmap that we can readback into
341 SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
342 kPremul_SkAlphaType);
343 SkBitmap bitmap;
344 bitmap.allocPixels(imageInfo);
345
Adlai Hollerf19bbb52020-06-29 10:00:08 -0400346 sk_sp<SkDeferredDisplayList> ddl;
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500347
348 // First, create a DDL using the stock SkSurface parameters
349 {
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400350 SurfaceParameters params(dContext);
Greg Daniel638b2e82020-08-27 14:29:00 -0400351 if (dContext->backend() == GrBackendApi::kVulkan) {
352 params.setVkRTInputAttachmentSupport(true);
353 }
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400354 ddl = params.createDDL(dContext);
Robert Phillipsfc711a22018-02-13 17:03:00 -0500355 SkAssertResult(ddl);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500356
357 // The DDL should draw into an SkSurface created with the same parameters
Robert Phillipsbe77a022018-04-03 17:17:05 -0400358 GrBackendTexture backend;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400359 sk_sp<SkSurface> s = params.make(dContext, &backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500360 if (!s) {
361 return;
362 }
363
Adlai Holler7580ad42020-06-24 13:45:25 -0400364 REPORTER_ASSERT(reporter, s->draw(ddl));
Robert Phillips9e441ee2018-02-01 15:14:55 -0500365 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400366 dContext->flushAndSubmit();
Robert Phillipsbe77a022018-04-03 17:17:05 -0400367 gpu->testingOnly_flushGpuAndSync();
368 s = nullptr;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400369 params.cleanUpBackEnd(dContext, backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500370 }
371
372 // Then, alter each parameter in turn and check that the DDL & surface are incompatible
373 for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400374 SurfaceParameters params(dContext);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500375 params.modify(i);
376
Robert Phillips3cd54322019-07-10 09:28:59 -0400377 if (SurfaceParameters::kProtectedCount == i) {
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400378 if (dContext->backend() != GrBackendApi::kVulkan) {
Robert Phillips3cd54322019-07-10 09:28:59 -0400379 // Only the Vulkan backend respects the protected parameter
380 continue;
381 }
382#ifdef SK_VULKAN
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400383 const GrVkCaps* vkCaps = (const GrVkCaps*) dContext->priv().caps();
Robert Phillips3cd54322019-07-10 09:28:59 -0400384
385 // And, even then, only when it is a protected context
386 if (!vkCaps->supportsProtectedMemory()) {
387 continue;
388 }
389#endif
390 }
391
Robert Phillipsbe77a022018-04-03 17:17:05 -0400392 GrBackendTexture backend;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400393 sk_sp<SkSurface> s = params.make(dContext, &backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500394 if (!s) {
395 continue;
396 }
397
398 if (SurfaceParameters::kSampleCount == i) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400399 int supportedSampleCount = caps->getRenderTargetSampleCount(
Greg Daniel6fa62e22019-08-07 15:52:37 -0400400 params.sampleCount(), backend.getBackendFormat());
Brian Salomonbdecacf2018-02-02 20:32:49 -0500401 if (1 == supportedSampleCount) {
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500402 // If changing the sample count won't result in a different
403 // surface characterization, skip this step
Robert Phillipsbe77a022018-04-03 17:17:05 -0400404 s = nullptr;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400405 params.cleanUpBackEnd(dContext, backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500406 continue;
407 }
408 }
409
Brian Salomon69100f02020-07-21 10:49:25 -0400410 if (SurfaceParameters::kMipMipCount == i && !caps->mipmapSupport()) {
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400411 // If changing the mipmap setting won't result in a different surface characterization,
412 // skip this step
Robert Phillipsbe77a022018-04-03 17:17:05 -0400413 s = nullptr;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400414 params.cleanUpBackEnd(dContext, backend);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500415 continue;
416 }
417
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400418 if (SurfaceParameters::kFBO0Count == i && dContext->backend() != GrBackendApi::kOpenGL) {
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500419 // FBO0 only affects the surface characterization when using OpenGL
420 s = nullptr;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400421 params.cleanUpBackEnd(dContext, backend);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500422 continue;
423 }
424
Adlai Holler7580ad42020-06-24 13:45:25 -0400425 REPORTER_ASSERT(reporter, !s->draw(ddl),
Robert Phillipse8fabb22018-02-04 14:33:21 -0500426 "DDLSurfaceCharacterizationTest failed on parameter: %d\n", i);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400427
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400428 dContext->flushAndSubmit();
Robert Phillipsbe77a022018-04-03 17:17:05 -0400429 gpu->testingOnly_flushGpuAndSync();
430 s = nullptr;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400431 params.cleanUpBackEnd(dContext, backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500432 }
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500433
434 // Next test the compatibility of resource cache parameters
435 {
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400436 const SurfaceParameters params(dContext);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400437 GrBackendTexture backend;
438
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400439 sk_sp<SkSurface> s = params.make(dContext, &backend);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500440
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400441 size_t maxResourceBytes = dContext->getResourceCacheLimit();
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500442
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400443 dContext->setResourceCacheLimit(maxResourceBytes/2);
Adlai Holler7580ad42020-06-24 13:45:25 -0400444 REPORTER_ASSERT(reporter, !s->draw(ddl));
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500445
Robert Phillips9e441ee2018-02-01 15:14:55 -0500446 // DDL TODO: once proxies/ops can be de-instantiated we can re-enable these tests.
447 // For now, DDLs are drawn once.
448#if 0
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500449 // resource limits >= those at characterization time are accepted
450 context->setResourceCacheLimits(2*maxResourceCount, maxResourceBytes);
Adlai Holler7580ad42020-06-24 13:45:25 -0400451 REPORTER_ASSERT(reporter, s->draw(ddl));
Robert Phillips9e441ee2018-02-01 15:14:55 -0500452 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500453
454 context->setResourceCacheLimits(maxResourceCount, 2*maxResourceBytes);
Adlai Holler7580ad42020-06-24 13:45:25 -0400455 REPORTER_ASSERT(reporter, s->draw(ddl));
Robert Phillips9e441ee2018-02-01 15:14:55 -0500456 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500457
458 context->setResourceCacheLimits(maxResourceCount, maxResourceBytes);
Adlai Holler7580ad42020-06-24 13:45:25 -0400459 REPORTER_ASSERT(reporter, s->draw(ddl));
Robert Phillips9e441ee2018-02-01 15:14:55 -0500460 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
461#endif
Robert Phillipsbe77a022018-04-03 17:17:05 -0400462
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400463 dContext->flushAndSubmit();
Robert Phillipsbe77a022018-04-03 17:17:05 -0400464 gpu->testingOnly_flushGpuAndSync();
465 s = nullptr;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400466 params.cleanUpBackEnd(dContext, backend);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500467 }
468
Robert Phillipse8fabb22018-02-04 14:33:21 -0500469 // Test that the textureability of the DDL characterization can block a DDL draw
470 {
471 GrBackendTexture backend;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400472 SurfaceParameters params(dContext);
Robert Phillipsc046ff02019-07-01 10:34:03 -0400473 params.setShouldCreateMipMaps(false);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500474 params.setTextureable(false);
475
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400476 sk_sp<SkSurface> s = params.make(dContext, &backend);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500477 if (s) {
Adlai Holler7580ad42020-06-24 13:45:25 -0400478 REPORTER_ASSERT(reporter, !s->draw(ddl)); // bc the DDL was made w/ textureability
Robert Phillipse8fabb22018-02-04 14:33:21 -0500479
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400480 dContext->flushAndSubmit();
Robert Phillipsbe77a022018-04-03 17:17:05 -0400481 gpu->testingOnly_flushGpuAndSync();
Robert Phillipse8fabb22018-02-04 14:33:21 -0500482 s = nullptr;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400483 params.cleanUpBackEnd(dContext, backend);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500484 }
485 }
486
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500487 // Make sure non-GPU-backed surfaces fail characterization
488 {
489 SkImageInfo ii = SkImageInfo::MakeN32(64, 64, kOpaque_SkAlphaType);
490
491 sk_sp<SkSurface> rasterSurface = SkSurface::MakeRaster(ii);
492 SkSurfaceCharacterization c;
493 REPORTER_ASSERT(reporter, !rasterSurface->characterize(&c));
494 }
Robert Phillips94458ee2018-03-06 13:41:51 -0500495
496 // Exercise the createResized method
497 {
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400498 SurfaceParameters params(dContext);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400499 GrBackendTexture backend;
Robert Phillips94458ee2018-03-06 13:41:51 -0500500
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400501 sk_sp<SkSurface> s = params.make(dContext, &backend);
Robert Phillips94458ee2018-03-06 13:41:51 -0500502 if (!s) {
503 return;
504 }
505
506 SkSurfaceCharacterization char0;
507 SkAssertResult(s->characterize(&char0));
508
509 // Too small
510 SkSurfaceCharacterization char1 = char0.createResized(-1, -1);
511 REPORTER_ASSERT(reporter, !char1.isValid());
512
513 // Too large
514 SkSurfaceCharacterization char2 = char0.createResized(1000000, 32);
515 REPORTER_ASSERT(reporter, !char2.isValid());
516
517 // Just right
518 SkSurfaceCharacterization char3 = char0.createResized(32, 32);
519 REPORTER_ASSERT(reporter, char3.isValid());
520 REPORTER_ASSERT(reporter, 32 == char3.width());
521 REPORTER_ASSERT(reporter, 32 == char3.height());
Robert Phillipsbe77a022018-04-03 17:17:05 -0400522
523 s = nullptr;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400524 params.cleanUpBackEnd(dContext, backend);
Robert Phillips94458ee2018-03-06 13:41:51 -0500525 }
Robert Phillipsa975ef32019-10-03 11:09:17 -0400526
527 // Exercise the createColorSpace method
528 {
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400529 SurfaceParameters params(dContext);
Robert Phillipsa975ef32019-10-03 11:09:17 -0400530 GrBackendTexture backend;
531
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400532 sk_sp<SkSurface> s = params.make(dContext, &backend);
Robert Phillipsa975ef32019-10-03 11:09:17 -0400533 if (!s) {
534 return;
535 }
536
537 SkSurfaceCharacterization char0;
538 SkAssertResult(s->characterize(&char0));
539
540 // The default params create an sRGB color space
541 REPORTER_ASSERT(reporter, char0.colorSpace()->isSRGB());
542 REPORTER_ASSERT(reporter, !char0.colorSpace()->gammaIsLinear());
543
544 {
545 sk_sp<SkColorSpace> newCS = SkColorSpace::MakeSRGBLinear();
546
547 SkSurfaceCharacterization char1 = char0.createColorSpace(std::move(newCS));
548 REPORTER_ASSERT(reporter, char1.isValid());
549 REPORTER_ASSERT(reporter, !char1.colorSpace()->isSRGB());
550 REPORTER_ASSERT(reporter, char1.colorSpace()->gammaIsLinear());
551 }
552
553 {
554 SkSurfaceCharacterization char2 = char0.createColorSpace(nullptr);
555 REPORTER_ASSERT(reporter, char2.isValid());
556 REPORTER_ASSERT(reporter, !char2.colorSpace());
557 }
558
559 {
560 sk_sp<SkColorSpace> newCS = SkColorSpace::MakeSRGBLinear();
561
562 SkSurfaceCharacterization invalid;
563 REPORTER_ASSERT(reporter, !invalid.isValid());
564 SkSurfaceCharacterization stillInvalid = invalid.createColorSpace(std::move(newCS));
565 REPORTER_ASSERT(reporter, !stillInvalid.isValid());
566 }
567
568 s = nullptr;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400569 params.cleanUpBackEnd(dContext, backend);
Robert Phillipsa975ef32019-10-03 11:09:17 -0400570 }
Robert Phillipsb3c061a2020-02-13 13:24:47 -0500571
572 // Exercise the createBackendFormat method
573 {
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400574 SurfaceParameters params(dContext);
Robert Phillipsb3c061a2020-02-13 13:24:47 -0500575 GrBackendTexture backend;
576
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400577 sk_sp<SkSurface> s = params.make(dContext, &backend);
Robert Phillipsb3c061a2020-02-13 13:24:47 -0500578 if (!s) {
579 return;
580 }
581
582 SkSurfaceCharacterization char0;
583 SkAssertResult(s->characterize(&char0));
584
585 // The default params create a renderable RGBA8 surface
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400586 auto originalBackendFormat = dContext->defaultBackendFormat(kRGBA_8888_SkColorType,
587 GrRenderable::kYes);
Robert Phillipsb3c061a2020-02-13 13:24:47 -0500588 REPORTER_ASSERT(reporter, originalBackendFormat.isValid());
589 REPORTER_ASSERT(reporter, char0.backendFormat() == originalBackendFormat);
590
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400591 auto newBackendFormat = dContext->defaultBackendFormat(kRGB_565_SkColorType,
592 GrRenderable::kYes);
Robert Phillipsb3c061a2020-02-13 13:24:47 -0500593
594 if (newBackendFormat.isValid()) {
595 SkSurfaceCharacterization char1 = char0.createBackendFormat(kRGB_565_SkColorType,
596 newBackendFormat);
597 REPORTER_ASSERT(reporter, char1.isValid());
598 REPORTER_ASSERT(reporter, char1.backendFormat() == newBackendFormat);
599
600 SkSurfaceCharacterization invalid;
601 REPORTER_ASSERT(reporter, !invalid.isValid());
602 auto stillInvalid = invalid.createBackendFormat(kRGB_565_SkColorType,
603 newBackendFormat);
604 REPORTER_ASSERT(reporter, !stillInvalid.isValid());
605 }
606
607 s = nullptr;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400608 params.cleanUpBackEnd(dContext, backend);
Robert Phillipsb3c061a2020-02-13 13:24:47 -0500609 }
610
611 // Exercise the createFBO0 method
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400612 if (dContext->backend() == GrBackendApi::kOpenGL) {
613 SurfaceParameters params(dContext);
Greg Daniel638b2e82020-08-27 14:29:00 -0400614 // If the original characterization is textureable then we will fail trying to make an
615 // FBO0 characterization
616 params.setTextureable(false);
617 params.setShouldCreateMipMaps(false);
Robert Phillipsb3c061a2020-02-13 13:24:47 -0500618 GrBackendTexture backend;
619
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400620 sk_sp<SkSurface> s = params.make(dContext, &backend);
Robert Phillipsb3c061a2020-02-13 13:24:47 -0500621 if (!s) {
622 return;
623 }
624
625 SkSurfaceCharacterization char0;
626 SkAssertResult(s->characterize(&char0));
627
628 // The default params create a non-FBO0 surface
629 REPORTER_ASSERT(reporter, !char0.usesGLFBO0());
630
631 {
632 SkSurfaceCharacterization char1 = char0.createFBO0(true);
633 REPORTER_ASSERT(reporter, char1.isValid());
634 REPORTER_ASSERT(reporter, char1.usesGLFBO0());
635 }
636
637 {
638 SkSurfaceCharacterization invalid;
639 REPORTER_ASSERT(reporter, !invalid.isValid());
640 SkSurfaceCharacterization stillInvalid = invalid.createFBO0(true);
641 REPORTER_ASSERT(reporter, !stillInvalid.isValid());
642 }
643
644 s = nullptr;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400645 params.cleanUpBackEnd(dContext, backend);
Robert Phillipsb3c061a2020-02-13 13:24:47 -0500646 }
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500647}
648
Robert Phillips2dbcbe82020-03-05 11:16:39 -0500649#ifdef SK_GL
650
651// Test out the surface compatibility checks regarding FBO0-ness. This test constructs
652// two parallel arrays of characterizations and surfaces in the order:
653// FBO0 w/ MSAA, FBO0 w/o MSAA, not-FBO0 w/ MSAA, not-FBO0 w/o MSAA
654// and then tries all sixteen combinations to check the expected compatibility.
655// Note: this is a GL-only test
656DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(CharacterizationFBO0nessTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400657 auto context = ctxInfo.directContext();
Robert Phillips2dbcbe82020-03-05 11:16:39 -0500658 const GrCaps* caps = context->priv().caps();
659 sk_sp<GrContextThreadSafeProxy> proxy = context->threadSafeProxy();
660 const size_t resourceCacheLimit = context->getResourceCacheLimit();
661
662 GrBackendFormat format = GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_2D);
663
664 int availableSamples = caps->getRenderTargetSampleCount(4, format);
665 if (availableSamples <= 1) {
666 // This context doesn't support MSAA for RGBA8
667 return;
668 }
669
670 SkImageInfo ii = SkImageInfo::Make({ 128, 128 }, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
671
672 static constexpr int kStencilBits = 8;
673 static constexpr bool kNotMipMapped = false;
674 static constexpr bool kNotTextureable = false;
675 const SkSurfaceProps surfaceProps(0x0, kRGB_H_SkPixelGeometry);
676
Robert Phillips1b1bd4e2020-03-05 13:21:12 -0500677 // Rows are characterizations and columns are surfaces
Robert Phillips2dbcbe82020-03-05 11:16:39 -0500678 static const bool kExpectedCompatibility[4][4] = {
Robert Phillips1b1bd4e2020-03-05 13:21:12 -0500679 // FBO0 & MSAA, FBO0 & not-MSAA, not-FBO0 & MSAA, not-FBO0 & not-MSAA
680/* FBO0 & MSAA */ { true, false, false, false },
681/* FBO0 & not-MSAA */ { false, true, false, true },
682/* not-FBO0 & MSAA */ { false, false, true, false },
683/* not-FBO0 & not- */ { false, false, false, true }
Robert Phillips2dbcbe82020-03-05 11:16:39 -0500684 };
685
686 SkSurfaceCharacterization characterizations[4];
687 sk_sp<SkSurface> surfaces[4];
688
689 int index = 0;
690 for (bool isFBO0 : { true, false }) {
691 for (int numSamples : { availableSamples, 1 }) {
692 characterizations[index] = proxy->createCharacterization(resourceCacheLimit,
693 ii, format, numSamples,
694 kTopLeft_GrSurfaceOrigin,
695 surfaceProps, kNotMipMapped,
696 isFBO0, kNotTextureable);
697 SkASSERT(characterizations[index].sampleCount() == numSamples);
698 SkASSERT(characterizations[index].usesGLFBO0() == isFBO0);
699
700 GrGLFramebufferInfo fboInfo{ isFBO0 ? 0 : (GrGLuint) 1, GR_GL_RGBA8 };
701 GrBackendRenderTarget backendRT(128, 128, numSamples, kStencilBits, fboInfo);
702 SkAssertResult(backendRT.isValid());
703
704 surfaces[index] = SkSurface::MakeFromBackendRenderTarget(context, backendRT,
705 kTopLeft_GrSurfaceOrigin,
706 kRGBA_8888_SkColorType,
707 nullptr, &surfaceProps);
708 ++index;
709 }
710 }
711
Robert Phillips1b1bd4e2020-03-05 13:21:12 -0500712 for (int c = 0; c < 4; ++c) {
713 for (int s = 0; s < 4; ++s) {
Robert Phillips2dbcbe82020-03-05 11:16:39 -0500714 REPORTER_ASSERT(reporter,
Robert Phillips1b1bd4e2020-03-05 13:21:12 -0500715 kExpectedCompatibility[c][s] ==
716 surfaces[s]->isCompatible(characterizations[c]));
Robert Phillips2dbcbe82020-03-05 11:16:39 -0500717 }
718 }
719}
720#endif
721
Robert Phillips3cd54322019-07-10 09:28:59 -0400722DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400723 auto context = ctxInfo.directContext();
Robert Phillips3cd54322019-07-10 09:28:59 -0400724
725 DDLSurfaceCharacterizationTestImpl(context, reporter);
726}
727
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500728// Test that a DDL created w/o textureability can be replayed into both a textureable and
729// non-textureable destination. Note that DDLSurfaceCharacterizationTest tests that a
730// textureable DDL cannot be played into a non-textureable destination but can be replayed
731// into a textureable destination.
732DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLNonTextureabilityTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400733 auto context = ctxInfo.directContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500734 GrGpu* gpu = context->priv().getGpu();
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500735
736 // Create a bitmap that we can readback into
737 SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
738 kPremul_SkAlphaType);
739 SkBitmap bitmap;
740 bitmap.allocPixels(imageInfo);
741
742 for (bool textureability : { true, false }) {
Adlai Hollerf19bbb52020-06-29 10:00:08 -0400743 sk_sp<SkDeferredDisplayList> ddl;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500744
Robert Phillipsc046ff02019-07-01 10:34:03 -0400745 // First, create a DDL w/o textureability (and thus no mipmaps). TODO: once we have
746 // reusable DDLs, move this outside of the loop.
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500747 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400748 SurfaceParameters params(context);
Robert Phillipsc046ff02019-07-01 10:34:03 -0400749 params.setShouldCreateMipMaps(false);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500750 params.setTextureable(false);
Greg Daniel638b2e82020-08-27 14:29:00 -0400751 if (context->backend() == GrBackendApi::kVulkan) {
752 params.setVkRTInputAttachmentSupport(true);
753 }
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500754
755 ddl = params.createDDL(context);
756 SkAssertResult(ddl);
757 }
758
759 // Then verify it can draw into either flavor of destination
Robert Phillips3cd54322019-07-10 09:28:59 -0400760 SurfaceParameters params(context);
Robert Phillipsc046ff02019-07-01 10:34:03 -0400761 params.setShouldCreateMipMaps(textureability);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500762 params.setTextureable(textureability);
Greg Daniel638b2e82020-08-27 14:29:00 -0400763 if (context->backend() == GrBackendApi::kVulkan) {
764 params.setVkRTInputAttachmentSupport(true);
765 }
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500766
767 GrBackendTexture backend;
768 sk_sp<SkSurface> s = params.make(context, &backend);
769 if (!s) {
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500770 continue;
771 }
772
Adlai Holler7580ad42020-06-24 13:45:25 -0400773 REPORTER_ASSERT(reporter, s->draw(ddl));
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500774 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400775 context->flushAndSubmit();
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500776 gpu->testingOnly_flushGpuAndSync();
777 s = nullptr;
778 params.cleanUpBackEnd(context, backend);
779 }
780
781}
782
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400783static void test_make_render_target(skiatest::Reporter* reporter,
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400784 GrDirectContext* dContext,
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400785 const SurfaceParameters& params) {
786 {
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400787 const SkSurfaceCharacterization c = params.createCharacterization(dContext);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400788
Robert Phillipsbe77a022018-04-03 17:17:05 -0400789 if (!c.isValid()) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400790 GrBackendTexture backend;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400791 sk_sp<SkSurface> tmp = params.make(dContext, &backend);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400792
793 // If we couldn't characterize the surface we shouldn't be able to create it either
794 REPORTER_ASSERT(reporter, !tmp);
795 if (tmp) {
796 tmp = nullptr;
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400797 params.cleanUpBackEnd(dContext, backend);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400798 }
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400799 return;
800 }
801 }
802
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400803 const SkSurfaceCharacterization c = params.createCharacterization(dContext);
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400804 GrBackendTexture backend;
805
806 {
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400807 sk_sp<SkSurface> s = params.make(dContext, &backend);
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400808 REPORTER_ASSERT(reporter, s);
809 if (!s) {
810 REPORTER_ASSERT(reporter, !c.isValid());
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400811 params.cleanUpBackEnd(dContext, backend);
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400812 return;
813 }
814
815 REPORTER_ASSERT(reporter, c.isValid());
Robert Phillipsc046ff02019-07-01 10:34:03 -0400816 REPORTER_ASSERT(reporter, c.isCompatible(backend));
Robert Phillips9907e6e2019-06-25 14:47:04 -0400817 REPORTER_ASSERT(reporter, s->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400818 // Note that we're leaving 'backend' live here
819 }
820
821 // Make an SkSurface from scratch
822 {
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400823 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(dContext, c, SkBudgeted::kYes);
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400824 REPORTER_ASSERT(reporter, s);
Robert Phillips9907e6e2019-06-25 14:47:04 -0400825 REPORTER_ASSERT(reporter, s->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400826 }
827
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400828 params.cleanUpBackEnd(dContext, backend);
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400829}
830
831////////////////////////////////////////////////////////////////////////////////
832// This tests the SkSurface::MakeRenderTarget variants that take an SkSurfaceCharacterization.
833// In particular, the SkSurface, backendTexture and SkSurfaceCharacterization
834// should always be compatible.
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400835void DDLMakeRenderTargetTestImpl(GrDirectContext* dContext, skiatest::Reporter* reporter) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400836 for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
837
838 if (SurfaceParameters::kFBO0Count == i) {
839 // MakeRenderTarget doesn't support FBO0
Robert Phillipsbe77a022018-04-03 17:17:05 -0400840 continue;
841 }
842
Robert Phillips3cd54322019-07-10 09:28:59 -0400843 if (SurfaceParameters::kProtectedCount == i) {
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400844 if (dContext->backend() != GrBackendApi::kVulkan) {
Robert Phillips3cd54322019-07-10 09:28:59 -0400845 // Only the Vulkan backend respects the protected parameter
846 continue;
847 }
848#ifdef SK_VULKAN
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400849 const GrVkCaps* vkCaps = (const GrVkCaps*) dContext->priv().caps();
Robert Phillips3cd54322019-07-10 09:28:59 -0400850
851 // And, even then, only when it is a protected context
852 if (!vkCaps->supportsProtectedMemory()) {
853 continue;
854 }
855#endif
856 }
857
858
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400859 SurfaceParameters params(dContext);
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400860 params.modify(i);
861
Brian Salomon69100f02020-07-21 10:49:25 -0400862 if (!dContext->priv().caps()->mipmapSupport()) {
Brian Salomon4687bdd2019-05-09 16:28:04 -0400863 params.setShouldCreateMipMaps(false);
864 }
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400865
Robert Phillipsc8ae4942020-07-20 10:56:01 -0400866 test_make_render_target(reporter, dContext, params);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400867 }
868}
869
Robert Phillips3cd54322019-07-10 09:28:59 -0400870DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMakeRenderTargetTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400871 auto context = ctxInfo.directContext();
Robert Phillips3cd54322019-07-10 09:28:59 -0400872
873 DDLMakeRenderTargetTestImpl(context, reporter);
874}
875
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400876////////////////////////////////////////////////////////////////////////////////
Greg Danielf2336e42018-01-23 16:38:14 -0500877static constexpr int kSize = 8;
878
879struct TextureReleaseChecker {
880 TextureReleaseChecker() : fReleaseCount(0) {}
881 int fReleaseCount;
882 static void Release(void* self) {
883 static_cast<TextureReleaseChecker*>(self)->fReleaseCount++;
884 }
885};
886
887enum class DDLStage { kMakeImage, kDrawImage, kDetach, kDrawDDL };
888
889// This tests the ability to create and use wrapped textures in a DDL world
890DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
Adlai Holler14dc7912020-08-11 15:48:49 +0000891 auto dContext = ctxInfo.directContext();
Robert Phillips9b16f812019-05-17 10:01:21 -0400892
Greg Danielc1ad77c2020-05-06 11:40:03 -0400893 GrBackendTexture backendTex;
Adlai Holler14dc7912020-08-11 15:48:49 +0000894 CreateBackendTexture(dContext, &backendTex, kSize, kSize, kRGBA_8888_SkColorType,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400895 SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo, GrProtected::kNo);
Brian Salomonf7778972018-03-08 10:13:17 -0500896 if (!backendTex.isValid()) {
897 return;
Greg Danielf2336e42018-01-23 16:38:14 -0500898 }
Brian Salomonf7778972018-03-08 10:13:17 -0500899
Adlai Holler14dc7912020-08-11 15:48:49 +0000900 SurfaceParameters params(dContext);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400901 GrBackendTexture backend;
Brian Salomonf7778972018-03-08 10:13:17 -0500902
Adlai Holler14dc7912020-08-11 15:48:49 +0000903 sk_sp<SkSurface> s = params.make(dContext, &backend);
Brian Salomonf7778972018-03-08 10:13:17 -0500904 if (!s) {
Adlai Holler14dc7912020-08-11 15:48:49 +0000905 dContext->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500906 return;
907 }
908
909 SkSurfaceCharacterization c;
910 SkAssertResult(s->characterize(&c));
911
Adlai Holler14dc7912020-08-11 15:48:49 +0000912 SkDeferredDisplayListRecorder recorder(c);
Brian Salomonf7778972018-03-08 10:13:17 -0500913
Adlai Holler14dc7912020-08-11 15:48:49 +0000914 SkCanvas* canvas = recorder.getCanvas();
915 SkASSERT(canvas);
Adlai Holler74b83a42020-08-06 17:24:53 +0000916
Adlai Holler14dc7912020-08-11 15:48:49 +0000917 auto rContext = canvas->recordingContext();
918 if (!rContext) {
Adlai Holler74b83a42020-08-06 17:24:53 +0000919 s = nullptr;
Adlai Holler14dc7912020-08-11 15:48:49 +0000920 params.cleanUpBackEnd(dContext, backend);
921 dContext->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500922 return;
923 }
924
925 // Wrapped Backend Textures are not supported in DDL
Brian Salomonf7778972018-03-08 10:13:17 -0500926 TextureReleaseChecker releaseChecker;
Adlai Hollere34b2822020-07-29 12:50:56 -0400927 sk_sp<SkImage> image =
Adlai Holler14dc7912020-08-11 15:48:49 +0000928 SkImage::MakeFromTexture(rContext, backendTex, kTopLeft_GrSurfaceOrigin,
Brian Salomonf7778972018-03-08 10:13:17 -0500929 kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr,
930 TextureReleaseChecker::Release, &releaseChecker);
931 REPORTER_ASSERT(reporter, !image);
932
Adlai Holler14dc7912020-08-11 15:48:49 +0000933 dContext->deleteBackendTexture(backendTex);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400934
935 s = nullptr;
Adlai Holler14dc7912020-08-11 15:48:49 +0000936 params.cleanUpBackEnd(dContext, backend);
Greg Danielf2336e42018-01-23 16:38:14 -0500937}
938
Brian Salomon59ef8c32019-01-30 12:20:56 -0500939static sk_sp<SkPromiseImageTexture> dummy_fulfill_proc(void*) {
940 SkASSERT(0);
941 return nullptr;
942}
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400943static void dummy_release_proc(void*) { SkASSERT(0); }
Brian Salomon59ef8c32019-01-30 12:20:56 -0500944static void dummy_done_proc(void*) {}
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400945
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400946////////////////////////////////////////////////////////////////////////////////
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400947// Test out the behavior of an invalid DDLRecorder
948DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLInvalidRecorder, reporter, ctxInfo) {
Robert Phillipsdc369702020-08-13 13:34:27 -0400949 auto dContext = ctxInfo.directContext();
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400950
951 {
952 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
Robert Phillipsdc369702020-08-13 13:34:27 -0400953 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, ii);
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400954
955 SkSurfaceCharacterization characterization;
956 SkAssertResult(s->characterize(&characterization));
957
958 // never calling getCanvas means the backing surface is never allocated
959 SkDeferredDisplayListRecorder recorder(characterization);
960 }
961
962 {
963 SkSurfaceCharacterization invalid;
964
965 SkDeferredDisplayListRecorder recorder(invalid);
966
967 const SkSurfaceCharacterization c = recorder.characterization();
968 REPORTER_ASSERT(reporter, !c.isValid());
969 REPORTER_ASSERT(reporter, !recorder.getCanvas());
970 REPORTER_ASSERT(reporter, !recorder.detach());
971
Robert Phillipsdc369702020-08-13 13:34:27 -0400972 GrBackendFormat format = dContext->defaultBackendFormat(kRGBA_8888_SkColorType,
973 GrRenderable::kNo);
Robert Phillips0a15cc62019-07-30 12:49:10 -0400974 SkASSERT(format.isValid());
Greg Daniel60ea40c2019-02-12 13:38:44 -0500975
Brian Salomonf55e8d52019-01-30 17:28:20 -0500976 sk_sp<SkImage> image = recorder.makePromiseTexture(
Brian Salomon7e67dca2020-07-21 09:27:25 -0400977 format, 32, 32, GrMipmapped::kNo,
Brian Salomonf55e8d52019-01-30 17:28:20 -0500978 kTopLeft_GrSurfaceOrigin,
979 kRGBA_8888_SkColorType,
980 kPremul_SkAlphaType, nullptr,
981 dummy_fulfill_proc,
982 dummy_release_proc,
983 dummy_done_proc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500984 nullptr,
985 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400986 REPORTER_ASSERT(reporter, !image);
987 }
Robert Phillipsdc369702020-08-13 13:34:27 -0400988}
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400989
Robert Phillipsdc369702020-08-13 13:34:27 -0400990DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLCreateCharacterizationFailures, reporter, ctxInfo) {
991 auto dContext = ctxInfo.directContext();
992 size_t maxResourceBytes = dContext->getResourceCacheLimit();
993 auto proxy = dContext->threadSafeProxy().get();
994
Greg Daniel638b2e82020-08-27 14:29:00 -0400995 auto check_create_fails =
996 [proxy, reporter, maxResourceBytes](const GrBackendFormat& backendFormat,
997 int width, int height,
998 SkColorType ct, bool willUseGLFBO0,
999 GrProtected prot,
1000 bool vkRTSupportsInputAttachment) {
Robert Phillipsdc369702020-08-13 13:34:27 -04001001 const SkSurfaceProps surfaceProps(0x0, kRGB_H_SkPixelGeometry);
1002
1003 SkImageInfo ii = SkImageInfo::Make(width, height, ct,
1004 kPremul_SkAlphaType, nullptr);
1005
1006 SkSurfaceCharacterization c = proxy->createCharacterization(
1007 maxResourceBytes, ii, backendFormat, 1,
1008 kBottomLeft_GrSurfaceOrigin, surfaceProps, false,
Greg Daniel638b2e82020-08-27 14:29:00 -04001009 willUseGLFBO0, true, prot,
1010 vkRTSupportsInputAttachment);
Robert Phillipsdc369702020-08-13 13:34:27 -04001011 REPORTER_ASSERT(reporter, !c.isValid());
1012 };
1013
1014 GrBackendFormat goodBackendFormat = dContext->defaultBackendFormat(kRGBA_8888_SkColorType,
1015 GrRenderable::kYes);
1016 SkASSERT(goodBackendFormat.isValid());
1017
1018 GrBackendFormat badBackendFormat;
1019 SkASSERT(!badBackendFormat.isValid());
1020
1021 SkColorType kGoodCT = kRGBA_8888_SkColorType;
1022 SkColorType kBadCT = kUnknown_SkColorType;
1023
1024 static const bool kGoodUseFBO0 = false;
1025 static const bool kBadUseFBO0 = true;
1026
Greg Daniel638b2e82020-08-27 14:29:00 -04001027 static const bool kGoodVkInputAttachment = false;
1028 static const bool kBadVkInputAttachment = true;
1029
Robert Phillipsdc369702020-08-13 13:34:27 -04001030 int goodWidth = 64;
1031 int goodHeight = 64;
1032 int badWidths[] = { 0, 1048576 };
1033 int badHeights[] = { 0, 1048576 };
1034
Greg Daniel638b2e82020-08-27 14:29:00 -04001035
1036 // In each of the check_create_fails calls there is one bad parameter that should cause the
1037 // creation of the characterization to fail.
1038 check_create_fails(goodBackendFormat, goodWidth, badHeights[0], kGoodCT, kGoodUseFBO0,
1039 GrProtected::kNo, kGoodVkInputAttachment);
1040 check_create_fails(goodBackendFormat, goodWidth, badHeights[1], kGoodCT, kGoodUseFBO0,
1041 GrProtected::kNo, kGoodVkInputAttachment);
1042 check_create_fails(goodBackendFormat, badWidths[0], goodHeight, kGoodCT, kGoodUseFBO0,
1043 GrProtected::kNo, kGoodVkInputAttachment);
1044 check_create_fails(goodBackendFormat, badWidths[1], goodHeight, kGoodCT, kGoodUseFBO0,
1045 GrProtected::kNo, kGoodVkInputAttachment);
1046 check_create_fails(badBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
1047 GrProtected::kNo, kGoodVkInputAttachment);
1048 check_create_fails(goodBackendFormat, goodWidth, goodHeight, kBadCT, kGoodUseFBO0,
1049 GrProtected::kNo, kGoodVkInputAttachment);
1050 // This fails because we always try to make a characterization that is textureable and we can't
1051 // have UseFBO0 be true and textureable.
1052 check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kBadUseFBO0,
1053 GrProtected::kNo, kGoodVkInputAttachment);
Robert Phillipsdc369702020-08-13 13:34:27 -04001054 if (dContext->backend() == GrBackendApi::kVulkan) {
Greg Daniel638b2e82020-08-27 14:29:00 -04001055 // The bad parameter in this case is the GrProtected::kYes since none of our test contexts
1056 // are made protected we can't have a protected surface.
1057 check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
1058 GrProtected::kYes, kGoodVkInputAttachment);
1059 } else {
1060 check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
1061 GrProtected::kNo, kBadVkInputAttachment);
Robert Phillipsdc369702020-08-13 13:34:27 -04001062 }
Robert Phillips6ceaafa2018-03-15 16:53:06 -04001063}
1064
Robert Phillips6b6fcc72018-03-30 13:57:00 -04001065////////////////////////////////////////////////////////////////////////////////
Robert Phillips874b5352018-03-16 08:48:24 -04001066// Ensure that flushing while DDL recording doesn't cause a crash
1067DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLFlushWhileRecording, reporter, ctxInfo) {
Robert Phillipsb27b38b2020-07-10 16:23:47 -04001068 auto direct = ctxInfo.directContext();
Robert Phillips874b5352018-03-16 08:48:24 -04001069
1070 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
Robert Phillipsb27b38b2020-07-10 16:23:47 -04001071 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(direct, SkBudgeted::kNo, ii);
Robert Phillips874b5352018-03-16 08:48:24 -04001072
1073 SkSurfaceCharacterization characterization;
1074 SkAssertResult(s->characterize(&characterization));
1075
1076 SkDeferredDisplayListRecorder recorder(characterization);
1077 SkCanvas* canvas = recorder.getCanvas();
1078
Robert Phillipsb27b38b2020-07-10 16:23:47 -04001079 // CONTEXT TODO: once getGrContext goes away this test should be deleted since this
1080 // situation won't be possible.
Greg Daniel0a2464f2020-05-14 15:45:44 -04001081 canvas->getGrContext()->flushAndSubmit();
Robert Phillips874b5352018-03-16 08:48:24 -04001082}
Greg Danielf2336e42018-01-23 16:38:14 -05001083
Robert Phillips6b6fcc72018-03-30 13:57:00 -04001084////////////////////////////////////////////////////////////////////////////////
Robert Phillipsee5fd132019-05-07 13:29:22 -04001085// Test that flushing a DDL via SkSurface::flush works
1086
1087struct FulfillInfo {
1088 sk_sp<SkPromiseImageTexture> fTex;
1089 bool fFulfilled = false;
1090 bool fReleased = false;
1091 bool fDone = false;
1092};
1093
1094static sk_sp<SkPromiseImageTexture> tracking_fulfill_proc(void* context) {
1095 FulfillInfo* info = (FulfillInfo*) context;
1096 info->fFulfilled = true;
1097 return info->fTex;
1098}
1099
1100static void tracking_release_proc(void* context) {
1101 FulfillInfo* info = (FulfillInfo*) context;
1102 info->fReleased = true;
1103}
1104
1105static void tracking_done_proc(void* context) {
1106 FulfillInfo* info = (FulfillInfo*) context;
1107 info->fDone = true;
1108}
1109
1110DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSkSurfaceFlush, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -04001111 auto context = ctxInfo.directContext();
Robert Phillipsee5fd132019-05-07 13:29:22 -04001112
1113 SkImageInfo ii = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
1114 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
1115
1116 SkSurfaceCharacterization characterization;
1117 SkAssertResult(s->characterize(&characterization));
1118
1119 GrBackendTexture backendTexture;
1120
Brian Salomon7e67dca2020-07-21 09:27:25 -04001121 if (!CreateBackendTexture(context, &backendTexture, ii, SkColors::kCyan, GrMipmapped::kNo,
Robert Phillips0efc01d2019-11-06 17:19:30 +00001122 GrRenderable::kNo)) {
Robert Phillipsee5fd132019-05-07 13:29:22 -04001123 REPORTER_ASSERT(reporter, false);
1124 return;
1125 }
1126
1127 FulfillInfo fulfillInfo;
1128 fulfillInfo.fTex = SkPromiseImageTexture::Make(backendTexture);
1129
Adlai Hollerf19bbb52020-06-29 10:00:08 -04001130 sk_sp<SkDeferredDisplayList> ddl;
Robert Phillipsee5fd132019-05-07 13:29:22 -04001131
1132 {
1133 SkDeferredDisplayListRecorder recorder(characterization);
1134
Robert Phillips0a15cc62019-07-30 12:49:10 -04001135 GrBackendFormat format = context->defaultBackendFormat(kRGBA_8888_SkColorType,
1136 GrRenderable::kNo);
1137 SkASSERT(format.isValid());
Robert Phillipsee5fd132019-05-07 13:29:22 -04001138
1139 sk_sp<SkImage> promiseImage = recorder.makePromiseTexture(
Brian Salomon7e67dca2020-07-21 09:27:25 -04001140 format, 32, 32, GrMipmapped::kNo,
Robert Phillipsee5fd132019-05-07 13:29:22 -04001141 kTopLeft_GrSurfaceOrigin,
1142 kRGBA_8888_SkColorType,
1143 kPremul_SkAlphaType, nullptr,
1144 tracking_fulfill_proc,
1145 tracking_release_proc,
1146 tracking_done_proc,
1147 &fulfillInfo,
1148 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
1149
1150 SkCanvas* canvas = recorder.getCanvas();
1151
1152 canvas->clear(SK_ColorRED);
1153 canvas->drawImage(promiseImage, 0, 0);
1154 ddl = recorder.detach();
1155 }
1156
Greg Daniel0a2464f2020-05-14 15:45:44 -04001157 context->flushAndSubmit();
Robert Phillips15c91422019-05-07 16:54:48 -04001158
Adlai Holler7580ad42020-06-24 13:45:25 -04001159 s->draw(ddl);
Robert Phillipsee5fd132019-05-07 13:29:22 -04001160
1161 GrFlushInfo flushInfo;
Robert Phillips8e49a692019-05-07 15:57:25 -04001162 s->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
Greg Daniel0a2464f2020-05-14 15:45:44 -04001163 context->submit();
Robert Phillipsee5fd132019-05-07 13:29:22 -04001164
1165 REPORTER_ASSERT(reporter, fulfillInfo.fFulfilled);
1166 REPORTER_ASSERT(reporter, fulfillInfo.fReleased);
1167
Robert Phillips8e49a692019-05-07 15:57:25 -04001168 if (GrBackendApi::kVulkan == context->backend() ||
1169 GrBackendApi::kMetal == context->backend()) {
Robert Phillips15c91422019-05-07 16:54:48 -04001170 // In order to receive the done callback with Vulkan we need to perform the equivalent
Robert Phillipsee5fd132019-05-07 13:29:22 -04001171 // of a glFinish
Greg Danielce9f0162020-06-30 13:42:46 -04001172 s->flush();
Greg Daniel0a2464f2020-05-14 15:45:44 -04001173 context->submit(true);
Robert Phillipsee5fd132019-05-07 13:29:22 -04001174 }
1175
1176 REPORTER_ASSERT(reporter, fulfillInfo.fDone);
1177
1178 REPORTER_ASSERT(reporter, fulfillInfo.fTex->unique());
1179 fulfillInfo.fTex.reset();
1180
Brian Salomon28a8f282019-10-24 20:07:39 -04001181 DeleteBackendTexture(context, backendTexture);
Robert Phillipsee5fd132019-05-07 13:29:22 -04001182}
1183
1184////////////////////////////////////////////////////////////////////////////////
Robert Phillipsf54883c2018-12-18 08:29:09 -05001185// Ensure that reusing a single DDLRecorder to create multiple DDLs works cleanly
1186DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMultipleDDLs, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -04001187 auto context = ctxInfo.directContext();
Robert Phillipsf54883c2018-12-18 08:29:09 -05001188
1189 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
1190 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
1191
1192 SkBitmap bitmap;
1193 bitmap.allocPixels(ii);
1194
1195 SkSurfaceCharacterization characterization;
1196 SkAssertResult(s->characterize(&characterization));
1197
1198 SkDeferredDisplayListRecorder recorder(characterization);
1199
1200 SkCanvas* canvas1 = recorder.getCanvas();
1201
1202 canvas1->clear(SK_ColorRED);
1203
1204 canvas1->save();
1205 canvas1->clipRect(SkRect::MakeXYWH(8, 8, 16, 16));
1206
Adlai Hollerf19bbb52020-06-29 10:00:08 -04001207 sk_sp<SkDeferredDisplayList> ddl1 = recorder.detach();
Robert Phillipsf54883c2018-12-18 08:29:09 -05001208
1209 SkCanvas* canvas2 = recorder.getCanvas();
1210
1211 SkPaint p;
1212 p.setColor(SK_ColorGREEN);
1213 canvas2->drawRect(SkRect::MakeWH(32, 32), p);
1214
Adlai Hollerf19bbb52020-06-29 10:00:08 -04001215 sk_sp<SkDeferredDisplayList> ddl2 = recorder.detach();
Robert Phillipsf54883c2018-12-18 08:29:09 -05001216
1217 REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData());
1218 REPORTER_ASSERT(reporter, ddl2->priv().lazyProxyData());
1219
1220 // The lazy proxy data being different ensures that the SkSurface, SkCanvas and backing-
1221 // lazy proxy are all different between the two DDLs
1222 REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData() != ddl2->priv().lazyProxyData());
1223
Adlai Holler7580ad42020-06-24 13:45:25 -04001224 s->draw(ddl1);
1225 s->draw(ddl2);
Robert Phillipsf54883c2018-12-18 08:29:09 -05001226
1227 // Make sure the clipRect from DDL1 didn't percolate into DDL2
1228 s->readPixels(ii, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
1229 for (int y = 0; y < 32; ++y) {
1230 for (int x = 0; x < 32; ++x) {
1231 REPORTER_ASSERT(reporter, bitmap.getColor(x, y) == SK_ColorGREEN);
1232 if (bitmap.getColor(x, y) != SK_ColorGREEN) {
1233 return; // we only really need to report the error once
1234 }
1235 }
1236 }
1237}
1238
John Rosascoa9b348f2019-11-08 13:18:15 -08001239#ifdef SK_GL
Robert Phillipsf54883c2018-12-18 08:29:09 -05001240////////////////////////////////////////////////////////////////////////////////
Robert Phillipsabf7b762018-03-21 12:13:37 -04001241// Check that the texture-specific flags (i.e., for external & rectangle textures) work
1242// for promise images. As such, this is a GL-only test.
1243DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLTextureFlagsTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -04001244 auto context = ctxInfo.directContext();
Robert Phillipsabf7b762018-03-21 12:13:37 -04001245
1246 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
1247 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
1248
1249 SkSurfaceCharacterization characterization;
1250 SkAssertResult(s->characterize(&characterization));
1251
1252 SkDeferredDisplayListRecorder recorder(characterization);
1253
1254 for (GrGLenum target : { GR_GL_TEXTURE_EXTERNAL, GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_2D } ) {
Brian Salomon7e67dca2020-07-21 09:27:25 -04001255 for (auto mipMapped : { GrMipmapped::kNo, GrMipmapped::kYes }) {
Greg Daniel09c94002018-06-08 22:11:51 +00001256 GrBackendFormat format = GrBackendFormat::MakeGL(GR_GL_RGBA8, target);
Robert Phillipsabf7b762018-03-21 12:13:37 -04001257
Brian Salomonf55e8d52019-01-30 17:28:20 -05001258 sk_sp<SkImage> image = recorder.makePromiseTexture(
1259 format, 32, 32, mipMapped,
1260 kTopLeft_GrSurfaceOrigin,
1261 kRGBA_8888_SkColorType,
1262 kPremul_SkAlphaType, nullptr,
1263 dummy_fulfill_proc,
1264 dummy_release_proc,
1265 dummy_done_proc,
Brian Salomon0cc57542019-03-08 13:28:46 -05001266 nullptr,
1267 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
Brian Salomon7e67dca2020-07-21 09:27:25 -04001268 if (GR_GL_TEXTURE_2D != target && mipMapped == GrMipmapped::kYes) {
Greg Daniel09c94002018-06-08 22:11:51 +00001269 REPORTER_ASSERT(reporter, !image);
1270 continue;
1271 }
1272 REPORTER_ASSERT(reporter, image);
Robert Phillipsabf7b762018-03-21 12:13:37 -04001273
Jim Van Verth21bd60d2018-10-12 15:00:20 -04001274 GrTextureProxy* backingProxy = ((SkImage_GpuBase*) image.get())->peekProxy();
Robert Phillipsabf7b762018-03-21 12:13:37 -04001275
Brian Salomon8c82a872020-07-21 12:09:58 -04001276 REPORTER_ASSERT(reporter, backingProxy->mipmapped() == mipMapped);
Greg Daniel09c94002018-06-08 22:11:51 +00001277 if (GR_GL_TEXTURE_2D == target) {
Brian Salomonfd98c2c2018-07-31 17:25:29 -04001278 REPORTER_ASSERT(reporter, !backingProxy->hasRestrictedSampling());
Greg Daniel09c94002018-06-08 22:11:51 +00001279 } else {
Brian Salomonfd98c2c2018-07-31 17:25:29 -04001280 REPORTER_ASSERT(reporter, backingProxy->hasRestrictedSampling());
Greg Daniel09c94002018-06-08 22:11:51 +00001281 }
Robert Phillipsabf7b762018-03-21 12:13:37 -04001282 }
1283 }
Robert Phillipsbe77a022018-04-03 17:17:05 -04001284}
John Rosascoa9b348f2019-11-08 13:18:15 -08001285#endif // SK_GL
Robert Phillipsbe77a022018-04-03 17:17:05 -04001286
1287////////////////////////////////////////////////////////////////////////////////
Robert Phillips646f6372018-09-25 09:31:10 -04001288// Test colorType and pixelConfig compatibility.
Robert Phillipsbe77a022018-04-03 17:17:05 -04001289DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLCompatibilityTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -04001290 auto context = ctxInfo.directContext();
Robert Phillipsbe77a022018-04-03 17:17:05 -04001291
1292 for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
1293 SkColorType colorType = static_cast<SkColorType>(ct);
1294
Robert Phillips3cd54322019-07-10 09:28:59 -04001295 SurfaceParameters params(context);
Greg Daniel60ea40c2019-02-12 13:38:44 -05001296 params.setColorType(colorType);
1297 params.setColorSpace(nullptr);
Robert Phillipsbe77a022018-04-03 17:17:05 -04001298
Brian Salomon69100f02020-07-21 10:49:25 -04001299 if (!context->priv().caps()->mipmapSupport()) {
Brian Salomon4687bdd2019-05-09 16:28:04 -04001300 params.setShouldCreateMipMaps(false);
1301 }
Greg Daniel60ea40c2019-02-12 13:38:44 -05001302
Robert Phillipsd8f79a22019-06-24 13:25:42 -04001303 test_make_render_target(reporter, context, params);
Robert Phillipsbe77a022018-04-03 17:17:05 -04001304 }
Robert Phillipsabf7b762018-03-21 12:13:37 -04001305
1306}