blob: 10d896db67b40b06b6363ad148f1c7f99f89ac4d [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"
12#include "include/core/SkDeferredDisplayListRecorder.h"
13#include "include/core/SkImage.h"
14#include "include/core/SkImageInfo.h"
15#include "include/core/SkPaint.h"
16#include "include/core/SkPromiseImageTexture.h"
17#include "include/core/SkRect.h"
18#include "include/core/SkRefCnt.h"
19#include "include/core/SkSurface.h"
20#include "include/core/SkSurfaceCharacterization.h"
21#include "include/core/SkSurfaceProps.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040022#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "include/gpu/GrBackendSurface.h"
24#include "include/gpu/GrContext.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040025#include "include/gpu/GrContextThreadSafeProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "include/gpu/GrTypes.h"
27#include "include/gpu/gl/GrGLTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#include "include/private/GrTypesPriv.h"
29#include "include/private/SkDeferredDisplayList.h"
30#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 Phillipsfc711a22018-02-13 17:03:00 -0500145 int maxResourceCount;
146 size_t maxResourceBytes;
147 context->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes);
148
149 // Note that Ganesh doesn't make use of the SkImageInfo's alphaType
150 SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType,
151 kPremul_SkAlphaType, fColorSpace);
152
Greg Daniel60ea40c2019-02-12 13:38:44 -0500153 const GrCaps* caps = context->priv().caps();
Greg Daniel627d0532019-07-08 16:48:14 -0400154 GrBackendFormat backendFormat =
155 caps->getBackendFormatFromColorType(SkColorTypeToGrColorType(fColorType));
Robert Phillipsbe77a022018-04-03 17:17:05 -0400156 if (!backendFormat.isValid()) {
157 return SkSurfaceCharacterization();
158 }
Robert Phillipsfc711a22018-02-13 17:03:00 -0500159
160 SkSurfaceCharacterization c = context->threadSafeProxy()->createCharacterization(
161 maxResourceBytes, ii, backendFormat, fSampleCount,
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500162 fOrigin, fSurfaceProps, fShouldCreateMipMaps,
Robert Phillips3cd54322019-07-10 09:28:59 -0400163 fUsesGLFBO0, fIsTextureable, fIsProtected);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400164 return c;
165 }
166
167 // Create a DDL whose characterization captures the current settings
168 std::unique_ptr<SkDeferredDisplayList> createDDL(GrContext* context) const {
169 SkSurfaceCharacterization c = this->createCharacterization(context);
Robert Phillipsfc711a22018-02-13 17:03:00 -0500170 SkAssertResult(c.isValid());
Robert Phillipse8fabb22018-02-04 14:33:21 -0500171
172 SkDeferredDisplayListRecorder r(c);
173 SkCanvas* canvas = r.getCanvas();
174 if (!canvas) {
175 return nullptr;
176 }
177
178 canvas->drawRect(SkRect::MakeXYWH(10, 10, 10, 10), SkPaint());
179 return r.detach();
180 }
181
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500182 // Create the surface with the current set of parameters
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500183 sk_sp<SkSurface> make(GrContext* context, GrBackendTexture* backend) const {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400184 const SkSurfaceCharacterization c = this->createCharacterization(context);
185
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500186 GrMipMapped mipmapped = !fIsTextureable
Robert Phillipsbe77a022018-04-03 17:17:05 -0400187 ? GrMipMapped::kNo
188 : GrMipMapped(fShouldCreateMipMaps);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500189
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500190 if (fUsesGLFBO0) {
191 if (GrBackendApi::kOpenGL != context->backend()) {
192 return nullptr;
193 }
194
195 GrGLFramebufferInfo fboInfo;
196 fboInfo.fFBOID = 0;
197 fboInfo.fFormat = GR_GL_RGBA8;
198 static constexpr int kStencilBits = 8;
199 GrBackendRenderTarget backendRT(fWidth, fHeight, 1, kStencilBits, fboInfo);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500200
201 if (!backendRT.isValid()) {
202 return nullptr;
203 }
204
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400205 sk_sp<SkSurface> result = SkSurface::MakeFromBackendRenderTarget(context, backendRT,
206 fOrigin, fColorType,
207 fColorSpace,
208 &fSurfaceProps);
Robert Phillips9907e6e2019-06-25 14:47:04 -0400209 SkASSERT(result->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400210 return result;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500211 }
212
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400213 *backend = context->createBackendTexture(fWidth, fHeight, fColorType,
214 SkColors::kTransparent,
Robert Phillips3cd54322019-07-10 09:28:59 -0400215 mipmapped, GrRenderable::kYes, fIsProtected);
Robert Phillips7c8af172019-07-08 15:55:24 -0400216 if (!backend->isValid()) {
Robert Phillipse8fabb22018-02-04 14:33:21 -0500217 return nullptr;
218 }
219
Robert Phillipsc046ff02019-07-01 10:34:03 -0400220 // Even if a characterization couldn't be constructed we want to soldier on to make
221 // sure that surface creation will/would've also failed
222 SkASSERT(!c.isValid() || c.isCompatible(*backend));
223
Robert Phillipsbe77a022018-04-03 17:17:05 -0400224 sk_sp<SkSurface> surface;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500225 if (!fIsTextureable) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400226 // Create a surface w/ the current parameters but make it non-textureable
227 surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
228 context, *backend, fOrigin, fSampleCount, fColorType,
229 fColorSpace, &fSurfaceProps);
230 } else {
231 surface = SkSurface::MakeFromBackendTexture(
232 context, *backend, fOrigin, fSampleCount, fColorType,
233 fColorSpace, &fSurfaceProps);
234 }
Robert Phillipse8fabb22018-02-04 14:33:21 -0500235
236 if (!surface) {
Robert Phillipsc046ff02019-07-01 10:34:03 -0400237 SkASSERT(!c.isValid());
Robert Phillips9b16f812019-05-17 10:01:21 -0400238 this->cleanUpBackEnd(context, *backend);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500239 return nullptr;
240 }
241
Robert Phillipsc046ff02019-07-01 10:34:03 -0400242 SkASSERT(c.isValid());
Robert Phillips9907e6e2019-06-25 14:47:04 -0400243 SkASSERT(surface->isCompatible(c));
Robert Phillipse8fabb22018-02-04 14:33:21 -0500244 return surface;
245 }
246
Brian Salomon26102cb2018-03-09 09:33:19 -0500247 void cleanUpBackEnd(GrContext* context, const GrBackendTexture& backend) const {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400248 context->deleteBackendTexture(backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500249 }
250
251private:
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500252 GrBackendApi fBackend;
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500253 int fWidth;
254 int fHeight;
255 GrSurfaceOrigin fOrigin;
256 SkColorType fColorType;
257 sk_sp<SkColorSpace> fColorSpace;
258 int fSampleCount;
259 SkSurfaceProps fSurfaceProps;
Robert Phillipse8fabb22018-02-04 14:33:21 -0500260 bool fShouldCreateMipMaps;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500261 bool fUsesGLFBO0;
262 bool fIsTextureable;
Robert Phillips3cd54322019-07-10 09:28:59 -0400263 GrProtected fIsProtected;
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500264};
265
Robert Phillipsc1267c62018-04-04 11:12:39 -0400266// Test out operator== && operator!=
267DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLOperatorEqTest, reporter, ctxInfo) {
268 GrContext* context = ctxInfo.grContext();
269
270 for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
Robert Phillips3cd54322019-07-10 09:28:59 -0400271 SurfaceParameters params1(context);
Robert Phillipsc1267c62018-04-04 11:12:39 -0400272 params1.modify(i);
273
274 SkSurfaceCharacterization char1 = params1.createCharacterization(context);
275 if (!char1.isValid()) {
276 continue; // can happen on some platforms (ChromeOS)
277 }
278
279 for (int j = 0; j < SurfaceParameters::kNumParams; ++j) {
Robert Phillips3cd54322019-07-10 09:28:59 -0400280 SurfaceParameters params2(context);
Robert Phillipsc1267c62018-04-04 11:12:39 -0400281 params2.modify(j);
282
283 SkSurfaceCharacterization char2 = params2.createCharacterization(context);
284 if (!char2.isValid()) {
285 continue; // can happen on some platforms (ChromeOS)
286 }
287
288 if (i == j) {
289 REPORTER_ASSERT(reporter, char1 == char2);
290 } else {
291 REPORTER_ASSERT(reporter, char1 != char2);
292 }
293
294 }
295 }
296
297 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400298 SurfaceParameters params(context);
Robert Phillipsc1267c62018-04-04 11:12:39 -0400299
300 SkSurfaceCharacterization valid = params.createCharacterization(context);
301 SkASSERT(valid.isValid());
302
303 SkSurfaceCharacterization inval1, inval2;
304 SkASSERT(!inval1.isValid() && !inval2.isValid());
305
306 REPORTER_ASSERT(reporter, inval1 != inval2);
307 REPORTER_ASSERT(reporter, valid != inval1);
308 REPORTER_ASSERT(reporter, inval1 != valid);
309 }
310}
311
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400312////////////////////////////////////////////////////////////////////////////////
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500313// This tests SkSurfaceCharacterization/SkSurface compatibility
Robert Phillips3cd54322019-07-10 09:28:59 -0400314void DDLSurfaceCharacterizationTestImpl(GrContext* context, skiatest::Reporter* reporter) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500315 GrGpu* gpu = context->priv().getGpu();
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400316 const GrCaps* caps = context->priv().caps();
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500317
Robert Phillips9e441ee2018-02-01 15:14:55 -0500318 // Create a bitmap that we can readback into
319 SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
320 kPremul_SkAlphaType);
321 SkBitmap bitmap;
322 bitmap.allocPixels(imageInfo);
323
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500324 std::unique_ptr<SkDeferredDisplayList> ddl;
325
326 // First, create a DDL using the stock SkSurface parameters
327 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400328 SurfaceParameters params(context);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500329
Robert Phillipse8fabb22018-02-04 14:33:21 -0500330 ddl = params.createDDL(context);
Robert Phillipsfc711a22018-02-13 17:03:00 -0500331 SkAssertResult(ddl);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500332
333 // The DDL should draw into an SkSurface created with the same parameters
Robert Phillipsbe77a022018-04-03 17:17:05 -0400334 GrBackendTexture backend;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500335 sk_sp<SkSurface> s = params.make(context, &backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500336 if (!s) {
337 return;
338 }
339
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500340 REPORTER_ASSERT(reporter, s->draw(ddl.get()));
Robert Phillips9e441ee2018-02-01 15:14:55 -0500341 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400342 context->flush();
343 gpu->testingOnly_flushGpuAndSync();
344 s = nullptr;
345 params.cleanUpBackEnd(context, backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500346 }
347
348 // Then, alter each parameter in turn and check that the DDL & surface are incompatible
349 for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
Robert Phillips3cd54322019-07-10 09:28:59 -0400350 SurfaceParameters params(context);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500351 params.modify(i);
352
Robert Phillips3cd54322019-07-10 09:28:59 -0400353 if (SurfaceParameters::kProtectedCount == i) {
354 if (context->backend() != GrBackendApi::kVulkan) {
355 // Only the Vulkan backend respects the protected parameter
356 continue;
357 }
358#ifdef SK_VULKAN
359 const GrVkCaps* vkCaps = (const GrVkCaps*) context->priv().caps();
360
361 // And, even then, only when it is a protected context
362 if (!vkCaps->supportsProtectedMemory()) {
363 continue;
364 }
365#endif
366 }
367
Robert Phillipsbe77a022018-04-03 17:17:05 -0400368 GrBackendTexture backend;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500369 sk_sp<SkSurface> s = params.make(context, &backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500370 if (!s) {
371 continue;
372 }
373
374 if (SurfaceParameters::kSampleCount == i) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400375 int supportedSampleCount = caps->getRenderTargetSampleCount(
Greg Daniel5c96db82019-07-09 14:06:58 -0400376 params.sampleCount(), SkColorTypeToGrColorType(params.colorType()),
377 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
405 context->flush();
406 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
418 int maxResourceCount;
419 size_t maxResourceBytes;
420 context->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes);
421
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500422 context->setResourceCacheLimits(maxResourceCount, maxResourceBytes/2);
423 REPORTER_ASSERT(reporter, !s->draw(ddl.get()));
424
Robert Phillips9e441ee2018-02-01 15:14:55 -0500425 // DDL TODO: once proxies/ops can be de-instantiated we can re-enable these tests.
426 // For now, DDLs are drawn once.
427#if 0
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500428 // resource limits >= those at characterization time are accepted
429 context->setResourceCacheLimits(2*maxResourceCount, maxResourceBytes);
430 REPORTER_ASSERT(reporter, s->draw(ddl.get()));
Robert Phillips9e441ee2018-02-01 15:14:55 -0500431 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500432
433 context->setResourceCacheLimits(maxResourceCount, 2*maxResourceBytes);
434 REPORTER_ASSERT(reporter, s->draw(ddl.get()));
Robert Phillips9e441ee2018-02-01 15:14:55 -0500435 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500436
437 context->setResourceCacheLimits(maxResourceCount, maxResourceBytes);
438 REPORTER_ASSERT(reporter, s->draw(ddl.get()));
Robert Phillips9e441ee2018-02-01 15:14:55 -0500439 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
440#endif
Robert Phillipsbe77a022018-04-03 17:17:05 -0400441
442 context->flush();
443 gpu->testingOnly_flushGpuAndSync();
444 s = nullptr;
445 params.cleanUpBackEnd(context, backend);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500446 }
447
Robert Phillipse8fabb22018-02-04 14:33:21 -0500448 // Test that the textureability of the DDL characterization can block a DDL draw
449 {
450 GrBackendTexture backend;
Robert Phillips3cd54322019-07-10 09:28:59 -0400451 SurfaceParameters params(context);
Robert Phillipsc046ff02019-07-01 10:34:03 -0400452 params.setShouldCreateMipMaps(false);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500453 params.setTextureable(false);
454
455 sk_sp<SkSurface> s = params.make(context, &backend);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500456 if (s) {
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500457 REPORTER_ASSERT(reporter, !s->draw(ddl.get())); // bc the DDL was made w/ textureability
Robert Phillipse8fabb22018-02-04 14:33:21 -0500458
Robert Phillipsbe77a022018-04-03 17:17:05 -0400459 context->flush();
460 gpu->testingOnly_flushGpuAndSync();
Robert Phillipse8fabb22018-02-04 14:33:21 -0500461 s = nullptr;
Brian Salomon26102cb2018-03-09 09:33:19 -0500462 params.cleanUpBackEnd(context, backend);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500463 }
464 }
465
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500466 // Make sure non-GPU-backed surfaces fail characterization
467 {
468 SkImageInfo ii = SkImageInfo::MakeN32(64, 64, kOpaque_SkAlphaType);
469
470 sk_sp<SkSurface> rasterSurface = SkSurface::MakeRaster(ii);
471 SkSurfaceCharacterization c;
472 REPORTER_ASSERT(reporter, !rasterSurface->characterize(&c));
473 }
Robert Phillips94458ee2018-03-06 13:41:51 -0500474
475 // Exercise the createResized method
476 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400477 SurfaceParameters params(context);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400478 GrBackendTexture backend;
Robert Phillips94458ee2018-03-06 13:41:51 -0500479
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500480 sk_sp<SkSurface> s = params.make(context, &backend);
Robert Phillips94458ee2018-03-06 13:41:51 -0500481 if (!s) {
482 return;
483 }
484
485 SkSurfaceCharacterization char0;
486 SkAssertResult(s->characterize(&char0));
487
488 // Too small
489 SkSurfaceCharacterization char1 = char0.createResized(-1, -1);
490 REPORTER_ASSERT(reporter, !char1.isValid());
491
492 // Too large
493 SkSurfaceCharacterization char2 = char0.createResized(1000000, 32);
494 REPORTER_ASSERT(reporter, !char2.isValid());
495
496 // Just right
497 SkSurfaceCharacterization char3 = char0.createResized(32, 32);
498 REPORTER_ASSERT(reporter, char3.isValid());
499 REPORTER_ASSERT(reporter, 32 == char3.width());
500 REPORTER_ASSERT(reporter, 32 == char3.height());
Robert Phillipsbe77a022018-04-03 17:17:05 -0400501
502 s = nullptr;
503 params.cleanUpBackEnd(context, backend);
Robert Phillips94458ee2018-03-06 13:41:51 -0500504 }
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500505}
506
Robert Phillips3cd54322019-07-10 09:28:59 -0400507DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo) {
508 GrContext* context = ctxInfo.grContext();
509
510 DDLSurfaceCharacterizationTestImpl(context, reporter);
511}
512
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500513// Test that a DDL created w/o textureability can be replayed into both a textureable and
514// non-textureable destination. Note that DDLSurfaceCharacterizationTest tests that a
515// textureable DDL cannot be played into a non-textureable destination but can be replayed
516// into a textureable destination.
517DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLNonTextureabilityTest, reporter, ctxInfo) {
518 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500519 GrGpu* gpu = context->priv().getGpu();
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500520
521 // Create a bitmap that we can readback into
522 SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
523 kPremul_SkAlphaType);
524 SkBitmap bitmap;
525 bitmap.allocPixels(imageInfo);
526
527 for (bool textureability : { true, false }) {
528 std::unique_ptr<SkDeferredDisplayList> ddl;
529
Robert Phillipsc046ff02019-07-01 10:34:03 -0400530 // First, create a DDL w/o textureability (and thus no mipmaps). TODO: once we have
531 // reusable DDLs, move this outside of the loop.
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500532 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400533 SurfaceParameters params(context);
Robert Phillipsc046ff02019-07-01 10:34:03 -0400534 params.setShouldCreateMipMaps(false);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500535 params.setTextureable(false);
536
537 ddl = params.createDDL(context);
538 SkAssertResult(ddl);
539 }
540
541 // Then verify it can draw into either flavor of destination
Robert Phillips3cd54322019-07-10 09:28:59 -0400542 SurfaceParameters params(context);
Robert Phillipsc046ff02019-07-01 10:34:03 -0400543 params.setShouldCreateMipMaps(textureability);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500544 params.setTextureable(textureability);
545
546 GrBackendTexture backend;
547 sk_sp<SkSurface> s = params.make(context, &backend);
548 if (!s) {
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500549 continue;
550 }
551
552 REPORTER_ASSERT(reporter, s->draw(ddl.get()));
553 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
554 context->flush();
555 gpu->testingOnly_flushGpuAndSync();
556 s = nullptr;
557 params.cleanUpBackEnd(context, backend);
558 }
559
560}
561
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400562static void test_make_render_target(skiatest::Reporter* reporter,
563 GrContext* context,
564 const SurfaceParameters& params) {
565 {
566 const SkSurfaceCharacterization c = params.createCharacterization(context);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400567
Robert Phillipsbe77a022018-04-03 17:17:05 -0400568 if (!c.isValid()) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400569 GrBackendTexture backend;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500570 sk_sp<SkSurface> tmp = params.make(context, &backend);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400571
572 // If we couldn't characterize the surface we shouldn't be able to create it either
573 REPORTER_ASSERT(reporter, !tmp);
574 if (tmp) {
575 tmp = nullptr;
576 params.cleanUpBackEnd(context, backend);
577 }
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400578 return;
579 }
580 }
581
582 const SkSurfaceCharacterization c = params.createCharacterization(context);
583 GrBackendTexture backend;
584
585 {
586 sk_sp<SkSurface> s = params.make(context, &backend);
587 REPORTER_ASSERT(reporter, s);
588 if (!s) {
589 REPORTER_ASSERT(reporter, !c.isValid());
590 params.cleanUpBackEnd(context, backend);
591 return;
592 }
593
594 REPORTER_ASSERT(reporter, c.isValid());
Robert Phillipsc046ff02019-07-01 10:34:03 -0400595 REPORTER_ASSERT(reporter, c.isCompatible(backend));
Robert Phillips9907e6e2019-06-25 14:47:04 -0400596 REPORTER_ASSERT(reporter, s->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400597 // Note that we're leaving 'backend' live here
598 }
599
600 // Make an SkSurface from scratch
601 {
602 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, c, SkBudgeted::kYes);
603 REPORTER_ASSERT(reporter, s);
Robert Phillips9907e6e2019-06-25 14:47:04 -0400604 REPORTER_ASSERT(reporter, s->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400605 }
606
Robert Phillips02dc0302019-07-02 17:58:27 -0400607 // Make an SkSurface that wraps the existing backend texture
608 {
609 sk_sp<SkSurface> s = SkSurface::MakeFromBackendTexture(context, c, backend);
610 REPORTER_ASSERT(reporter, s);
611 REPORTER_ASSERT(reporter, s->isCompatible(c));
612 }
613
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400614 params.cleanUpBackEnd(context, backend);
615}
616
617////////////////////////////////////////////////////////////////////////////////
618// This tests the SkSurface::MakeRenderTarget variants that take an SkSurfaceCharacterization.
619// In particular, the SkSurface, backendTexture and SkSurfaceCharacterization
620// should always be compatible.
Robert Phillips3cd54322019-07-10 09:28:59 -0400621void DDLMakeRenderTargetTestImpl(GrContext* context, skiatest::Reporter* reporter) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400622 for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
623
624 if (SurfaceParameters::kFBO0Count == i) {
625 // MakeRenderTarget doesn't support FBO0
Robert Phillipsbe77a022018-04-03 17:17:05 -0400626 continue;
627 }
628
Robert Phillips3cd54322019-07-10 09:28:59 -0400629 if (SurfaceParameters::kProtectedCount == i) {
630 if (context->backend() != GrBackendApi::kVulkan) {
631 // Only the Vulkan backend respects the protected parameter
632 continue;
633 }
634#ifdef SK_VULKAN
635 const GrVkCaps* vkCaps = (const GrVkCaps*) context->priv().caps();
636
637 // And, even then, only when it is a protected context
638 if (!vkCaps->supportsProtectedMemory()) {
639 continue;
640 }
641#endif
642 }
643
644
645 SurfaceParameters params(context);
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400646 params.modify(i);
647
Brian Salomon4687bdd2019-05-09 16:28:04 -0400648 if (!context->priv().caps()->mipMapSupport()) {
649 params.setShouldCreateMipMaps(false);
650 }
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400651
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400652 test_make_render_target(reporter, context, params);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400653 }
654}
655
Robert Phillips3cd54322019-07-10 09:28:59 -0400656DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMakeRenderTargetTest, reporter, ctxInfo) {
657 GrContext* context = ctxInfo.grContext();
658
659 DDLMakeRenderTargetTestImpl(context, reporter);
660}
661
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400662////////////////////////////////////////////////////////////////////////////////
Greg Danielf2336e42018-01-23 16:38:14 -0500663static constexpr int kSize = 8;
664
665struct TextureReleaseChecker {
666 TextureReleaseChecker() : fReleaseCount(0) {}
667 int fReleaseCount;
668 static void Release(void* self) {
669 static_cast<TextureReleaseChecker*>(self)->fReleaseCount++;
670 }
671};
672
673enum class DDLStage { kMakeImage, kDrawImage, kDetach, kDrawDDL };
674
675// This tests the ability to create and use wrapped textures in a DDL world
676DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
677 GrContext* context = ctxInfo.grContext();
Robert Phillips9b16f812019-05-17 10:01:21 -0400678
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400679 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400680 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400681 SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
Brian Salomonf7778972018-03-08 10:13:17 -0500682 if (!backendTex.isValid()) {
683 return;
Greg Danielf2336e42018-01-23 16:38:14 -0500684 }
Brian Salomonf7778972018-03-08 10:13:17 -0500685
Robert Phillips3cd54322019-07-10 09:28:59 -0400686 SurfaceParameters params(context);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400687 GrBackendTexture backend;
Brian Salomonf7778972018-03-08 10:13:17 -0500688
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500689 sk_sp<SkSurface> s = params.make(context, &backend);
Brian Salomonf7778972018-03-08 10:13:17 -0500690 if (!s) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400691 context->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500692 return;
693 }
694
695 SkSurfaceCharacterization c;
696 SkAssertResult(s->characterize(&c));
697
698 std::unique_ptr<SkDeferredDisplayListRecorder> recorder(new SkDeferredDisplayListRecorder(c));
699
700 SkCanvas* canvas = recorder->getCanvas();
701 if (!canvas) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400702 s = nullptr;
703 params.cleanUpBackEnd(context, backend);
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400704 context->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500705 return;
706 }
707
708 GrContext* deferredContext = canvas->getGrContext();
709 if (!deferredContext) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400710 s = nullptr;
711 params.cleanUpBackEnd(context, backend);
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400712 context->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500713 return;
714 }
715
716 // Wrapped Backend Textures are not supported in DDL
717 sk_sp<SkImage> image =
718 SkImage::MakeFromAdoptedTexture(deferredContext, backendTex, kTopLeft_GrSurfaceOrigin,
719 kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
720 REPORTER_ASSERT(reporter, !image);
721
722 TextureReleaseChecker releaseChecker;
723 image = SkImage::MakeFromTexture(deferredContext, backendTex, kTopLeft_GrSurfaceOrigin,
724 kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr,
725 TextureReleaseChecker::Release, &releaseChecker);
726 REPORTER_ASSERT(reporter, !image);
727
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400728 context->deleteBackendTexture(backendTex);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400729
730 s = nullptr;
731 params.cleanUpBackEnd(context, backend);
Greg Danielf2336e42018-01-23 16:38:14 -0500732}
733
Brian Salomon59ef8c32019-01-30 12:20:56 -0500734static sk_sp<SkPromiseImageTexture> dummy_fulfill_proc(void*) {
735 SkASSERT(0);
736 return nullptr;
737}
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400738static void dummy_release_proc(void*) { SkASSERT(0); }
Brian Salomon59ef8c32019-01-30 12:20:56 -0500739static void dummy_done_proc(void*) {}
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400740
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400741////////////////////////////////////////////////////////////////////////////////
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400742// Test out the behavior of an invalid DDLRecorder
743DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLInvalidRecorder, reporter, ctxInfo) {
744 GrContext* context = ctxInfo.grContext();
745
746 {
747 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
748 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
749
750 SkSurfaceCharacterization characterization;
751 SkAssertResult(s->characterize(&characterization));
752
753 // never calling getCanvas means the backing surface is never allocated
754 SkDeferredDisplayListRecorder recorder(characterization);
755 }
756
757 {
758 SkSurfaceCharacterization invalid;
759
760 SkDeferredDisplayListRecorder recorder(invalid);
761
762 const SkSurfaceCharacterization c = recorder.characterization();
763 REPORTER_ASSERT(reporter, !c.isValid());
764 REPORTER_ASSERT(reporter, !recorder.getCanvas());
765 REPORTER_ASSERT(reporter, !recorder.detach());
766
Greg Daniel60ea40c2019-02-12 13:38:44 -0500767 const GrCaps* caps = context->priv().caps();
Greg Daniel627d0532019-07-08 16:48:14 -0400768 GrBackendFormat format = caps->getBackendFormatFromColorType(GrColorType::kRGBA_8888);
Greg Daniel60ea40c2019-02-12 13:38:44 -0500769
Brian Salomonf55e8d52019-01-30 17:28:20 -0500770 sk_sp<SkImage> image = recorder.makePromiseTexture(
771 format, 32, 32, GrMipMapped::kNo,
772 kTopLeft_GrSurfaceOrigin,
773 kRGBA_8888_SkColorType,
774 kPremul_SkAlphaType, nullptr,
775 dummy_fulfill_proc,
776 dummy_release_proc,
777 dummy_done_proc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500778 nullptr,
779 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400780 REPORTER_ASSERT(reporter, !image);
781 }
782
783}
784
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400785////////////////////////////////////////////////////////////////////////////////
Robert Phillips874b5352018-03-16 08:48:24 -0400786// Ensure that flushing while DDL recording doesn't cause a crash
787DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLFlushWhileRecording, reporter, ctxInfo) {
788 GrContext* context = ctxInfo.grContext();
789
790 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
791 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
792
793 SkSurfaceCharacterization characterization;
794 SkAssertResult(s->characterize(&characterization));
795
796 SkDeferredDisplayListRecorder recorder(characterization);
797 SkCanvas* canvas = recorder.getCanvas();
798
Robert Phillips874b5352018-03-16 08:48:24 -0400799 canvas->getGrContext()->flush();
800}
Greg Danielf2336e42018-01-23 16:38:14 -0500801
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400802////////////////////////////////////////////////////////////////////////////////
Robert Phillipsee5fd132019-05-07 13:29:22 -0400803// Test that flushing a DDL via SkSurface::flush works
804
805struct FulfillInfo {
806 sk_sp<SkPromiseImageTexture> fTex;
807 bool fFulfilled = false;
808 bool fReleased = false;
809 bool fDone = false;
810};
811
812static sk_sp<SkPromiseImageTexture> tracking_fulfill_proc(void* context) {
813 FulfillInfo* info = (FulfillInfo*) context;
814 info->fFulfilled = true;
815 return info->fTex;
816}
817
818static void tracking_release_proc(void* context) {
819 FulfillInfo* info = (FulfillInfo*) context;
820 info->fReleased = true;
821}
822
823static void tracking_done_proc(void* context) {
824 FulfillInfo* info = (FulfillInfo*) context;
825 info->fDone = true;
826}
827
828DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSkSurfaceFlush, reporter, ctxInfo) {
829 GrContext* context = ctxInfo.grContext();
830
831 SkImageInfo ii = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
832 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
833
834 SkSurfaceCharacterization characterization;
835 SkAssertResult(s->characterize(&characterization));
836
837 GrBackendTexture backendTexture;
838
839 if (!create_backend_texture(context, &backendTexture, ii, GrMipMapped::kNo, SK_ColorCYAN,
Robert Phillips9dbcdcc2019-05-13 10:40:06 -0400840 GrRenderable::kNo)) {
Robert Phillipsee5fd132019-05-07 13:29:22 -0400841 REPORTER_ASSERT(reporter, false);
842 return;
843 }
844
845 FulfillInfo fulfillInfo;
846 fulfillInfo.fTex = SkPromiseImageTexture::Make(backendTexture);
847
848 std::unique_ptr<SkDeferredDisplayList> ddl;
849
850 {
851 SkDeferredDisplayListRecorder recorder(characterization);
852
853 const GrCaps* caps = context->priv().caps();
Greg Daniel627d0532019-07-08 16:48:14 -0400854 GrBackendFormat format = caps->getBackendFormatFromColorType(GrColorType::kRGBA_8888);
Robert Phillipsee5fd132019-05-07 13:29:22 -0400855
856 sk_sp<SkImage> promiseImage = recorder.makePromiseTexture(
857 format, 32, 32, GrMipMapped::kNo,
858 kTopLeft_GrSurfaceOrigin,
859 kRGBA_8888_SkColorType,
860 kPremul_SkAlphaType, nullptr,
861 tracking_fulfill_proc,
862 tracking_release_proc,
863 tracking_done_proc,
864 &fulfillInfo,
865 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
866
867 SkCanvas* canvas = recorder.getCanvas();
868
869 canvas->clear(SK_ColorRED);
870 canvas->drawImage(promiseImage, 0, 0);
871 ddl = recorder.detach();
872 }
873
Robert Phillips15c91422019-05-07 16:54:48 -0400874 context->flush();
875
Robert Phillipsee5fd132019-05-07 13:29:22 -0400876 s->draw(ddl.get());
877
878 GrFlushInfo flushInfo;
Robert Phillips8e49a692019-05-07 15:57:25 -0400879 s->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
Robert Phillipsee5fd132019-05-07 13:29:22 -0400880
881 REPORTER_ASSERT(reporter, fulfillInfo.fFulfilled);
882 REPORTER_ASSERT(reporter, fulfillInfo.fReleased);
883
Robert Phillips8e49a692019-05-07 15:57:25 -0400884 if (GrBackendApi::kVulkan == context->backend() ||
885 GrBackendApi::kMetal == context->backend()) {
Robert Phillips15c91422019-05-07 16:54:48 -0400886 // In order to receive the done callback with Vulkan we need to perform the equivalent
Robert Phillipsee5fd132019-05-07 13:29:22 -0400887 // of a glFinish
888 GrFlushInfo flushInfoSyncCpu;
889 flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
Robert Phillips8e49a692019-05-07 15:57:25 -0400890 s->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfoSyncCpu);
Robert Phillipsee5fd132019-05-07 13:29:22 -0400891 }
892
893 REPORTER_ASSERT(reporter, fulfillInfo.fDone);
894
895 REPORTER_ASSERT(reporter, fulfillInfo.fTex->unique());
896 fulfillInfo.fTex.reset();
897
898 delete_backend_texture(context, backendTexture);
899}
900
901////////////////////////////////////////////////////////////////////////////////
Robert Phillipsf54883c2018-12-18 08:29:09 -0500902// Ensure that reusing a single DDLRecorder to create multiple DDLs works cleanly
903DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMultipleDDLs, reporter, ctxInfo) {
904 GrContext* context = ctxInfo.grContext();
905
906 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
907 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
908
909 SkBitmap bitmap;
910 bitmap.allocPixels(ii);
911
912 SkSurfaceCharacterization characterization;
913 SkAssertResult(s->characterize(&characterization));
914
915 SkDeferredDisplayListRecorder recorder(characterization);
916
917 SkCanvas* canvas1 = recorder.getCanvas();
918
919 canvas1->clear(SK_ColorRED);
920
921 canvas1->save();
922 canvas1->clipRect(SkRect::MakeXYWH(8, 8, 16, 16));
923
924 std::unique_ptr<SkDeferredDisplayList> ddl1 = recorder.detach();
925
926 SkCanvas* canvas2 = recorder.getCanvas();
927
928 SkPaint p;
929 p.setColor(SK_ColorGREEN);
930 canvas2->drawRect(SkRect::MakeWH(32, 32), p);
931
932 std::unique_ptr<SkDeferredDisplayList> ddl2 = recorder.detach();
933
934 REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData());
935 REPORTER_ASSERT(reporter, ddl2->priv().lazyProxyData());
936
937 // The lazy proxy data being different ensures that the SkSurface, SkCanvas and backing-
938 // lazy proxy are all different between the two DDLs
939 REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData() != ddl2->priv().lazyProxyData());
940
941 s->draw(ddl1.get());
942 s->draw(ddl2.get());
943
944 // Make sure the clipRect from DDL1 didn't percolate into DDL2
945 s->readPixels(ii, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
946 for (int y = 0; y < 32; ++y) {
947 for (int x = 0; x < 32; ++x) {
948 REPORTER_ASSERT(reporter, bitmap.getColor(x, y) == SK_ColorGREEN);
949 if (bitmap.getColor(x, y) != SK_ColorGREEN) {
950 return; // we only really need to report the error once
951 }
952 }
953 }
954}
955
956////////////////////////////////////////////////////////////////////////////////
Robert Phillipsabf7b762018-03-21 12:13:37 -0400957// Check that the texture-specific flags (i.e., for external & rectangle textures) work
958// for promise images. As such, this is a GL-only test.
959DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLTextureFlagsTest, reporter, ctxInfo) {
960 GrContext* context = ctxInfo.grContext();
961
962 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
963 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
964
965 SkSurfaceCharacterization characterization;
966 SkAssertResult(s->characterize(&characterization));
967
968 SkDeferredDisplayListRecorder recorder(characterization);
969
970 for (GrGLenum target : { GR_GL_TEXTURE_EXTERNAL, GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_2D } ) {
Greg Daniel09c94002018-06-08 22:11:51 +0000971 for (auto mipMapped : { GrMipMapped::kNo, GrMipMapped::kYes }) {
972 GrBackendFormat format = GrBackendFormat::MakeGL(GR_GL_RGBA8, target);
Robert Phillipsabf7b762018-03-21 12:13:37 -0400973
Brian Salomonf55e8d52019-01-30 17:28:20 -0500974 sk_sp<SkImage> image = recorder.makePromiseTexture(
975 format, 32, 32, mipMapped,
976 kTopLeft_GrSurfaceOrigin,
977 kRGBA_8888_SkColorType,
978 kPremul_SkAlphaType, nullptr,
979 dummy_fulfill_proc,
980 dummy_release_proc,
981 dummy_done_proc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500982 nullptr,
983 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
Greg Daniel09c94002018-06-08 22:11:51 +0000984 if (GR_GL_TEXTURE_2D != target && mipMapped == GrMipMapped::kYes) {
985 REPORTER_ASSERT(reporter, !image);
986 continue;
987 }
988 REPORTER_ASSERT(reporter, image);
Robert Phillipsabf7b762018-03-21 12:13:37 -0400989
Jim Van Verth21bd60d2018-10-12 15:00:20 -0400990 GrTextureProxy* backingProxy = ((SkImage_GpuBase*) image.get())->peekProxy();
Robert Phillipsabf7b762018-03-21 12:13:37 -0400991
Greg Daniel09c94002018-06-08 22:11:51 +0000992 REPORTER_ASSERT(reporter, backingProxy->mipMapped() == mipMapped);
993 if (GR_GL_TEXTURE_2D == target) {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400994 REPORTER_ASSERT(reporter, !backingProxy->hasRestrictedSampling());
Greg Daniel09c94002018-06-08 22:11:51 +0000995 } else {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400996 REPORTER_ASSERT(reporter, backingProxy->hasRestrictedSampling());
Greg Daniel09c94002018-06-08 22:11:51 +0000997 }
Robert Phillipsabf7b762018-03-21 12:13:37 -0400998 }
999 }
Robert Phillipsbe77a022018-04-03 17:17:05 -04001000}
1001
1002////////////////////////////////////////////////////////////////////////////////
Robert Phillips646f6372018-09-25 09:31:10 -04001003// Test colorType and pixelConfig compatibility.
Robert Phillipsbe77a022018-04-03 17:17:05 -04001004DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLCompatibilityTest, reporter, ctxInfo) {
1005 GrContext* context = ctxInfo.grContext();
1006
1007 for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
1008 SkColorType colorType = static_cast<SkColorType>(ct);
1009
Robert Phillips3cd54322019-07-10 09:28:59 -04001010 SurfaceParameters params(context);
Greg Daniel60ea40c2019-02-12 13:38:44 -05001011 params.setColorType(colorType);
1012 params.setColorSpace(nullptr);
Robert Phillipsbe77a022018-04-03 17:17:05 -04001013
Brian Salomon4687bdd2019-05-09 16:28:04 -04001014 if (!context->priv().caps()->mipMapSupport()) {
1015 params.setShouldCreateMipMaps(false);
1016 }
Greg Daniel60ea40c2019-02-12 13:38:44 -05001017
Robert Phillipsd8f79a22019-06-24 13:25:42 -04001018 test_make_render_target(reporter, context, params);
Robert Phillipsbe77a022018-04-03 17:17:05 -04001019 }
Robert Phillipsabf7b762018-03-21 12:13:37 -04001020
1021}