blob: d31fcb6781d3ec341b937bf4ced323a5ce2f357a [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 Phillipscf39f372019-09-03 10:29:20 -0400145 size_t maxResourceBytes = context->getResourceCacheLimit();
Robert Phillipsfc711a22018-02-13 17:03:00 -0500146
Robert Phillipsd470e1b2019-09-04 15:05:35 -0400147 if (!context->colorTypeSupportedAsSurface(fColorType)) {
148 return SkSurfaceCharacterization();
149 }
150
Robert Phillipsfc711a22018-02-13 17:03:00 -0500151 // Note that Ganesh doesn't make use of the SkImageInfo's alphaType
152 SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType,
153 kPremul_SkAlphaType, fColorSpace);
154
Robert Phillips0a15cc62019-07-30 12:49:10 -0400155 GrBackendFormat backendFormat = context->defaultBackendFormat(fColorType,
156 GrRenderable::kYes);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400157 if (!backendFormat.isValid()) {
158 return SkSurfaceCharacterization();
159 }
Robert Phillipsfc711a22018-02-13 17:03:00 -0500160
161 SkSurfaceCharacterization c = context->threadSafeProxy()->createCharacterization(
162 maxResourceBytes, ii, backendFormat, fSampleCount,
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500163 fOrigin, fSurfaceProps, fShouldCreateMipMaps,
Robert Phillips3cd54322019-07-10 09:28:59 -0400164 fUsesGLFBO0, fIsTextureable, fIsProtected);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400165 return c;
166 }
167
168 // Create a DDL whose characterization captures the current settings
169 std::unique_ptr<SkDeferredDisplayList> createDDL(GrContext* context) const {
170 SkSurfaceCharacterization c = this->createCharacterization(context);
Robert Phillipsfc711a22018-02-13 17:03:00 -0500171 SkAssertResult(c.isValid());
Robert Phillipse8fabb22018-02-04 14:33:21 -0500172
173 SkDeferredDisplayListRecorder r(c);
174 SkCanvas* canvas = r.getCanvas();
175 if (!canvas) {
176 return nullptr;
177 }
178
179 canvas->drawRect(SkRect::MakeXYWH(10, 10, 10, 10), SkPaint());
180 return r.detach();
181 }
182
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500183 // Create the surface with the current set of parameters
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500184 sk_sp<SkSurface> make(GrContext* context, GrBackendTexture* backend) const {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400185 const SkSurfaceCharacterization c = this->createCharacterization(context);
186
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500187 GrMipMapped mipmapped = !fIsTextureable
Robert Phillipsbe77a022018-04-03 17:17:05 -0400188 ? GrMipMapped::kNo
189 : GrMipMapped(fShouldCreateMipMaps);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500190
John Rosasco24cbdab2019-09-25 14:14:35 -0700191#ifdef SK_GL
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500192 if (fUsesGLFBO0) {
193 if (GrBackendApi::kOpenGL != context->backend()) {
194 return nullptr;
195 }
196
197 GrGLFramebufferInfo fboInfo;
198 fboInfo.fFBOID = 0;
199 fboInfo.fFormat = GR_GL_RGBA8;
200 static constexpr int kStencilBits = 8;
201 GrBackendRenderTarget backendRT(fWidth, fHeight, 1, kStencilBits, fboInfo);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500202
203 if (!backendRT.isValid()) {
204 return nullptr;
205 }
206
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400207 sk_sp<SkSurface> result = SkSurface::MakeFromBackendRenderTarget(context, backendRT,
208 fOrigin, fColorType,
209 fColorSpace,
210 &fSurfaceProps);
Robert Phillips9907e6e2019-06-25 14:47:04 -0400211 SkASSERT(result->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400212 return result;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500213 }
John Rosasco24cbdab2019-09-25 14:14:35 -0700214#endif
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500215
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400216 *backend = context->createBackendTexture(fWidth, fHeight, fColorType,
217 SkColors::kTransparent,
Robert Phillips3cd54322019-07-10 09:28:59 -0400218 mipmapped, GrRenderable::kYes, fIsProtected);
Robert Phillips7c8af172019-07-08 15:55:24 -0400219 if (!backend->isValid()) {
Robert Phillipse8fabb22018-02-04 14:33:21 -0500220 return nullptr;
221 }
222
Robert Phillipsc046ff02019-07-01 10:34:03 -0400223 // Even if a characterization couldn't be constructed we want to soldier on to make
224 // sure that surface creation will/would've also failed
225 SkASSERT(!c.isValid() || c.isCompatible(*backend));
226
Robert Phillipsbe77a022018-04-03 17:17:05 -0400227 sk_sp<SkSurface> surface;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500228 if (!fIsTextureable) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400229 // Create a surface w/ the current parameters but make it non-textureable
230 surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
231 context, *backend, fOrigin, fSampleCount, fColorType,
232 fColorSpace, &fSurfaceProps);
233 } else {
234 surface = SkSurface::MakeFromBackendTexture(
235 context, *backend, fOrigin, fSampleCount, fColorType,
236 fColorSpace, &fSurfaceProps);
237 }
Robert Phillipse8fabb22018-02-04 14:33:21 -0500238
239 if (!surface) {
Robert Phillipsc046ff02019-07-01 10:34:03 -0400240 SkASSERT(!c.isValid());
Robert Phillips9b16f812019-05-17 10:01:21 -0400241 this->cleanUpBackEnd(context, *backend);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500242 return nullptr;
243 }
244
Robert Phillipsc046ff02019-07-01 10:34:03 -0400245 SkASSERT(c.isValid());
Robert Phillips9907e6e2019-06-25 14:47:04 -0400246 SkASSERT(surface->isCompatible(c));
Robert Phillipse8fabb22018-02-04 14:33:21 -0500247 return surface;
248 }
249
Brian Salomon26102cb2018-03-09 09:33:19 -0500250 void cleanUpBackEnd(GrContext* context, const GrBackendTexture& backend) const {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400251 context->deleteBackendTexture(backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500252 }
253
254private:
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500255 GrBackendApi fBackend;
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500256 int fWidth;
257 int fHeight;
258 GrSurfaceOrigin fOrigin;
259 SkColorType fColorType;
260 sk_sp<SkColorSpace> fColorSpace;
261 int fSampleCount;
262 SkSurfaceProps fSurfaceProps;
Robert Phillipse8fabb22018-02-04 14:33:21 -0500263 bool fShouldCreateMipMaps;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500264 bool fUsesGLFBO0;
265 bool fIsTextureable;
Robert Phillips3cd54322019-07-10 09:28:59 -0400266 GrProtected fIsProtected;
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500267};
268
Robert Phillipsc1267c62018-04-04 11:12:39 -0400269// Test out operator== && operator!=
270DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLOperatorEqTest, reporter, ctxInfo) {
271 GrContext* context = ctxInfo.grContext();
272
273 for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
Robert Phillips3cd54322019-07-10 09:28:59 -0400274 SurfaceParameters params1(context);
Robert Phillipsc1267c62018-04-04 11:12:39 -0400275 params1.modify(i);
276
277 SkSurfaceCharacterization char1 = params1.createCharacterization(context);
278 if (!char1.isValid()) {
279 continue; // can happen on some platforms (ChromeOS)
280 }
281
282 for (int j = 0; j < SurfaceParameters::kNumParams; ++j) {
Robert Phillips3cd54322019-07-10 09:28:59 -0400283 SurfaceParameters params2(context);
Robert Phillipsc1267c62018-04-04 11:12:39 -0400284 params2.modify(j);
285
286 SkSurfaceCharacterization char2 = params2.createCharacterization(context);
287 if (!char2.isValid()) {
288 continue; // can happen on some platforms (ChromeOS)
289 }
290
291 if (i == j) {
292 REPORTER_ASSERT(reporter, char1 == char2);
293 } else {
294 REPORTER_ASSERT(reporter, char1 != char2);
295 }
296
297 }
298 }
299
300 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400301 SurfaceParameters params(context);
Robert Phillipsc1267c62018-04-04 11:12:39 -0400302
303 SkSurfaceCharacterization valid = params.createCharacterization(context);
304 SkASSERT(valid.isValid());
305
306 SkSurfaceCharacterization inval1, inval2;
307 SkASSERT(!inval1.isValid() && !inval2.isValid());
308
309 REPORTER_ASSERT(reporter, inval1 != inval2);
310 REPORTER_ASSERT(reporter, valid != inval1);
311 REPORTER_ASSERT(reporter, inval1 != valid);
312 }
313}
314
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400315////////////////////////////////////////////////////////////////////////////////
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500316// This tests SkSurfaceCharacterization/SkSurface compatibility
Robert Phillips3cd54322019-07-10 09:28:59 -0400317void DDLSurfaceCharacterizationTestImpl(GrContext* context, skiatest::Reporter* reporter) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500318 GrGpu* gpu = context->priv().getGpu();
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400319 const GrCaps* caps = context->priv().caps();
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500320
Robert Phillips9e441ee2018-02-01 15:14:55 -0500321 // Create a bitmap that we can readback into
322 SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
323 kPremul_SkAlphaType);
324 SkBitmap bitmap;
325 bitmap.allocPixels(imageInfo);
326
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500327 std::unique_ptr<SkDeferredDisplayList> ddl;
328
329 // First, create a DDL using the stock SkSurface parameters
330 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400331 SurfaceParameters params(context);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500332
Robert Phillipse8fabb22018-02-04 14:33:21 -0500333 ddl = params.createDDL(context);
Robert Phillipsfc711a22018-02-13 17:03:00 -0500334 SkAssertResult(ddl);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500335
336 // The DDL should draw into an SkSurface created with the same parameters
Robert Phillipsbe77a022018-04-03 17:17:05 -0400337 GrBackendTexture backend;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500338 sk_sp<SkSurface> s = params.make(context, &backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500339 if (!s) {
340 return;
341 }
342
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500343 REPORTER_ASSERT(reporter, s->draw(ddl.get()));
Robert Phillips9e441ee2018-02-01 15:14:55 -0500344 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400345 context->flush();
346 gpu->testingOnly_flushGpuAndSync();
347 s = nullptr;
348 params.cleanUpBackEnd(context, backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500349 }
350
351 // Then, alter each parameter in turn and check that the DDL & surface are incompatible
352 for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
Robert Phillips3cd54322019-07-10 09:28:59 -0400353 SurfaceParameters params(context);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500354 params.modify(i);
355
Robert Phillips3cd54322019-07-10 09:28:59 -0400356 if (SurfaceParameters::kProtectedCount == i) {
357 if (context->backend() != GrBackendApi::kVulkan) {
358 // Only the Vulkan backend respects the protected parameter
359 continue;
360 }
361#ifdef SK_VULKAN
362 const GrVkCaps* vkCaps = (const GrVkCaps*) context->priv().caps();
363
364 // And, even then, only when it is a protected context
365 if (!vkCaps->supportsProtectedMemory()) {
366 continue;
367 }
368#endif
369 }
370
Robert Phillipsbe77a022018-04-03 17:17:05 -0400371 GrBackendTexture backend;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500372 sk_sp<SkSurface> s = params.make(context, &backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500373 if (!s) {
374 continue;
375 }
376
377 if (SurfaceParameters::kSampleCount == i) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400378 int supportedSampleCount = caps->getRenderTargetSampleCount(
Greg Daniel6fa62e22019-08-07 15:52:37 -0400379 params.sampleCount(), backend.getBackendFormat());
Brian Salomonbdecacf2018-02-02 20:32:49 -0500380 if (1 == supportedSampleCount) {
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500381 // If changing the sample count won't result in a different
382 // surface characterization, skip this step
Robert Phillipsbe77a022018-04-03 17:17:05 -0400383 s = nullptr;
384 params.cleanUpBackEnd(context, backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500385 continue;
386 }
387 }
388
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400389 if (SurfaceParameters::kMipMipCount == i && !caps->mipMapSupport()) {
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400390 // If changing the mipmap setting won't result in a different surface characterization,
391 // skip this step
Robert Phillipsbe77a022018-04-03 17:17:05 -0400392 s = nullptr;
393 params.cleanUpBackEnd(context, backend);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500394 continue;
395 }
396
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500397 if (SurfaceParameters::kFBO0Count == i && context->backend() != GrBackendApi::kOpenGL) {
398 // FBO0 only affects the surface characterization when using OpenGL
399 s = nullptr;
400 params.cleanUpBackEnd(context, backend);
401 continue;
402 }
403
Robert Phillipse8fabb22018-02-04 14:33:21 -0500404 REPORTER_ASSERT(reporter, !s->draw(ddl.get()),
405 "DDLSurfaceCharacterizationTest failed on parameter: %d\n", i);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400406
407 context->flush();
408 gpu->testingOnly_flushGpuAndSync();
409 s = nullptr;
410 params.cleanUpBackEnd(context, backend);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500411 }
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500412
413 // Next test the compatibility of resource cache parameters
414 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400415 const SurfaceParameters params(context);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400416 GrBackendTexture backend;
417
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500418 sk_sp<SkSurface> s = params.make(context, &backend);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500419
Robert Phillipscf39f372019-09-03 10:29:20 -0400420 size_t maxResourceBytes = context->getResourceCacheLimit();
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500421
Robert Phillipscf39f372019-09-03 10:29:20 -0400422 context->setResourceCacheLimit(maxResourceBytes/2);
Robert Phillips8d1e67e2017-12-04 13:48:14 -0500423 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 Phillipsa975ef32019-10-03 11:09:17 -0400505
506 // Exercise the createColorSpace method
507 {
508 SurfaceParameters params(context);
509 GrBackendTexture backend;
510
511 sk_sp<SkSurface> s = params.make(context, &backend);
512 if (!s) {
513 return;
514 }
515
516 SkSurfaceCharacterization char0;
517 SkAssertResult(s->characterize(&char0));
518
519 // The default params create an sRGB color space
520 REPORTER_ASSERT(reporter, char0.colorSpace()->isSRGB());
521 REPORTER_ASSERT(reporter, !char0.colorSpace()->gammaIsLinear());
522
523 {
524 sk_sp<SkColorSpace> newCS = SkColorSpace::MakeSRGBLinear();
525
526 SkSurfaceCharacterization char1 = char0.createColorSpace(std::move(newCS));
527 REPORTER_ASSERT(reporter, char1.isValid());
528 REPORTER_ASSERT(reporter, !char1.colorSpace()->isSRGB());
529 REPORTER_ASSERT(reporter, char1.colorSpace()->gammaIsLinear());
530 }
531
532 {
533 SkSurfaceCharacterization char2 = char0.createColorSpace(nullptr);
534 REPORTER_ASSERT(reporter, char2.isValid());
535 REPORTER_ASSERT(reporter, !char2.colorSpace());
536 }
537
538 {
539 sk_sp<SkColorSpace> newCS = SkColorSpace::MakeSRGBLinear();
540
541 SkSurfaceCharacterization invalid;
542 REPORTER_ASSERT(reporter, !invalid.isValid());
543 SkSurfaceCharacterization stillInvalid = invalid.createColorSpace(std::move(newCS));
544 REPORTER_ASSERT(reporter, !stillInvalid.isValid());
545 }
546
547 s = nullptr;
548 params.cleanUpBackEnd(context, backend);
549 }
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500550}
551
Robert Phillips3cd54322019-07-10 09:28:59 -0400552DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo) {
553 GrContext* context = ctxInfo.grContext();
554
555 DDLSurfaceCharacterizationTestImpl(context, reporter);
556}
557
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500558// Test that a DDL created w/o textureability can be replayed into both a textureable and
559// non-textureable destination. Note that DDLSurfaceCharacterizationTest tests that a
560// textureable DDL cannot be played into a non-textureable destination but can be replayed
561// into a textureable destination.
562DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLNonTextureabilityTest, reporter, ctxInfo) {
563 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500564 GrGpu* gpu = context->priv().getGpu();
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500565
566 // Create a bitmap that we can readback into
567 SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
568 kPremul_SkAlphaType);
569 SkBitmap bitmap;
570 bitmap.allocPixels(imageInfo);
571
572 for (bool textureability : { true, false }) {
573 std::unique_ptr<SkDeferredDisplayList> ddl;
574
Robert Phillipsc046ff02019-07-01 10:34:03 -0400575 // First, create a DDL w/o textureability (and thus no mipmaps). TODO: once we have
576 // reusable DDLs, move this outside of the loop.
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500577 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400578 SurfaceParameters params(context);
Robert Phillipsc046ff02019-07-01 10:34:03 -0400579 params.setShouldCreateMipMaps(false);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500580 params.setTextureable(false);
581
582 ddl = params.createDDL(context);
583 SkAssertResult(ddl);
584 }
585
586 // Then verify it can draw into either flavor of destination
Robert Phillips3cd54322019-07-10 09:28:59 -0400587 SurfaceParameters params(context);
Robert Phillipsc046ff02019-07-01 10:34:03 -0400588 params.setShouldCreateMipMaps(textureability);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500589 params.setTextureable(textureability);
590
591 GrBackendTexture backend;
592 sk_sp<SkSurface> s = params.make(context, &backend);
593 if (!s) {
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500594 continue;
595 }
596
597 REPORTER_ASSERT(reporter, s->draw(ddl.get()));
598 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
599 context->flush();
600 gpu->testingOnly_flushGpuAndSync();
601 s = nullptr;
602 params.cleanUpBackEnd(context, backend);
603 }
604
605}
606
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400607static void test_make_render_target(skiatest::Reporter* reporter,
608 GrContext* context,
609 const SurfaceParameters& params) {
610 {
611 const SkSurfaceCharacterization c = params.createCharacterization(context);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400612
Robert Phillipsbe77a022018-04-03 17:17:05 -0400613 if (!c.isValid()) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400614 GrBackendTexture backend;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500615 sk_sp<SkSurface> tmp = params.make(context, &backend);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400616
617 // If we couldn't characterize the surface we shouldn't be able to create it either
618 REPORTER_ASSERT(reporter, !tmp);
619 if (tmp) {
620 tmp = nullptr;
621 params.cleanUpBackEnd(context, backend);
622 }
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400623 return;
624 }
625 }
626
627 const SkSurfaceCharacterization c = params.createCharacterization(context);
628 GrBackendTexture backend;
629
630 {
631 sk_sp<SkSurface> s = params.make(context, &backend);
632 REPORTER_ASSERT(reporter, s);
633 if (!s) {
634 REPORTER_ASSERT(reporter, !c.isValid());
635 params.cleanUpBackEnd(context, backend);
636 return;
637 }
638
639 REPORTER_ASSERT(reporter, c.isValid());
Robert Phillipsc046ff02019-07-01 10:34:03 -0400640 REPORTER_ASSERT(reporter, c.isCompatible(backend));
Robert Phillips9907e6e2019-06-25 14:47:04 -0400641 REPORTER_ASSERT(reporter, s->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400642 // Note that we're leaving 'backend' live here
643 }
644
645 // Make an SkSurface from scratch
646 {
647 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, c, SkBudgeted::kYes);
648 REPORTER_ASSERT(reporter, s);
Robert Phillips9907e6e2019-06-25 14:47:04 -0400649 REPORTER_ASSERT(reporter, s->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400650 }
651
Robert Phillips02dc0302019-07-02 17:58:27 -0400652 // Make an SkSurface that wraps the existing backend texture
653 {
654 sk_sp<SkSurface> s = SkSurface::MakeFromBackendTexture(context, c, backend);
655 REPORTER_ASSERT(reporter, s);
656 REPORTER_ASSERT(reporter, s->isCompatible(c));
657 }
658
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400659 params.cleanUpBackEnd(context, backend);
660}
661
662////////////////////////////////////////////////////////////////////////////////
663// This tests the SkSurface::MakeRenderTarget variants that take an SkSurfaceCharacterization.
664// In particular, the SkSurface, backendTexture and SkSurfaceCharacterization
665// should always be compatible.
Robert Phillips3cd54322019-07-10 09:28:59 -0400666void DDLMakeRenderTargetTestImpl(GrContext* context, skiatest::Reporter* reporter) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400667 for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
668
669 if (SurfaceParameters::kFBO0Count == i) {
670 // MakeRenderTarget doesn't support FBO0
Robert Phillipsbe77a022018-04-03 17:17:05 -0400671 continue;
672 }
673
Robert Phillips3cd54322019-07-10 09:28:59 -0400674 if (SurfaceParameters::kProtectedCount == i) {
675 if (context->backend() != GrBackendApi::kVulkan) {
676 // Only the Vulkan backend respects the protected parameter
677 continue;
678 }
679#ifdef SK_VULKAN
680 const GrVkCaps* vkCaps = (const GrVkCaps*) context->priv().caps();
681
682 // And, even then, only when it is a protected context
683 if (!vkCaps->supportsProtectedMemory()) {
684 continue;
685 }
686#endif
687 }
688
689
690 SurfaceParameters params(context);
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400691 params.modify(i);
692
Brian Salomon4687bdd2019-05-09 16:28:04 -0400693 if (!context->priv().caps()->mipMapSupport()) {
694 params.setShouldCreateMipMaps(false);
695 }
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400696
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400697 test_make_render_target(reporter, context, params);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400698 }
699}
700
Robert Phillips3cd54322019-07-10 09:28:59 -0400701DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMakeRenderTargetTest, reporter, ctxInfo) {
702 GrContext* context = ctxInfo.grContext();
703
704 DDLMakeRenderTargetTestImpl(context, reporter);
705}
706
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400707////////////////////////////////////////////////////////////////////////////////
Greg Danielf2336e42018-01-23 16:38:14 -0500708static constexpr int kSize = 8;
709
710struct TextureReleaseChecker {
711 TextureReleaseChecker() : fReleaseCount(0) {}
712 int fReleaseCount;
713 static void Release(void* self) {
714 static_cast<TextureReleaseChecker*>(self)->fReleaseCount++;
715 }
716};
717
718enum class DDLStage { kMakeImage, kDrawImage, kDetach, kDrawDDL };
719
720// This tests the ability to create and use wrapped textures in a DDL world
721DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
722 GrContext* context = ctxInfo.grContext();
Robert Phillips9b16f812019-05-17 10:01:21 -0400723
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400724 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400725 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400726 SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
Brian Salomonf7778972018-03-08 10:13:17 -0500727 if (!backendTex.isValid()) {
728 return;
Greg Danielf2336e42018-01-23 16:38:14 -0500729 }
Brian Salomonf7778972018-03-08 10:13:17 -0500730
Robert Phillips3cd54322019-07-10 09:28:59 -0400731 SurfaceParameters params(context);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400732 GrBackendTexture backend;
Brian Salomonf7778972018-03-08 10:13:17 -0500733
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500734 sk_sp<SkSurface> s = params.make(context, &backend);
Brian Salomonf7778972018-03-08 10:13:17 -0500735 if (!s) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400736 context->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500737 return;
738 }
739
740 SkSurfaceCharacterization c;
741 SkAssertResult(s->characterize(&c));
742
743 std::unique_ptr<SkDeferredDisplayListRecorder> recorder(new SkDeferredDisplayListRecorder(c));
744
745 SkCanvas* canvas = recorder->getCanvas();
746 if (!canvas) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400747 s = nullptr;
748 params.cleanUpBackEnd(context, backend);
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400749 context->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500750 return;
751 }
752
753 GrContext* deferredContext = canvas->getGrContext();
754 if (!deferredContext) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400755 s = nullptr;
756 params.cleanUpBackEnd(context, backend);
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400757 context->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500758 return;
759 }
760
761 // Wrapped Backend Textures are not supported in DDL
762 sk_sp<SkImage> image =
763 SkImage::MakeFromAdoptedTexture(deferredContext, backendTex, kTopLeft_GrSurfaceOrigin,
764 kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
765 REPORTER_ASSERT(reporter, !image);
766
767 TextureReleaseChecker releaseChecker;
768 image = SkImage::MakeFromTexture(deferredContext, backendTex, kTopLeft_GrSurfaceOrigin,
769 kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr,
770 TextureReleaseChecker::Release, &releaseChecker);
771 REPORTER_ASSERT(reporter, !image);
772
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400773 context->deleteBackendTexture(backendTex);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400774
775 s = nullptr;
776 params.cleanUpBackEnd(context, backend);
Greg Danielf2336e42018-01-23 16:38:14 -0500777}
778
Brian Salomon59ef8c32019-01-30 12:20:56 -0500779static sk_sp<SkPromiseImageTexture> dummy_fulfill_proc(void*) {
780 SkASSERT(0);
781 return nullptr;
782}
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400783static void dummy_release_proc(void*) { SkASSERT(0); }
Brian Salomon59ef8c32019-01-30 12:20:56 -0500784static void dummy_done_proc(void*) {}
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400785
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400786////////////////////////////////////////////////////////////////////////////////
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400787// Test out the behavior of an invalid DDLRecorder
788DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLInvalidRecorder, reporter, ctxInfo) {
789 GrContext* context = ctxInfo.grContext();
790
791 {
792 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
793 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
794
795 SkSurfaceCharacterization characterization;
796 SkAssertResult(s->characterize(&characterization));
797
798 // never calling getCanvas means the backing surface is never allocated
799 SkDeferredDisplayListRecorder recorder(characterization);
800 }
801
802 {
803 SkSurfaceCharacterization invalid;
804
805 SkDeferredDisplayListRecorder recorder(invalid);
806
807 const SkSurfaceCharacterization c = recorder.characterization();
808 REPORTER_ASSERT(reporter, !c.isValid());
809 REPORTER_ASSERT(reporter, !recorder.getCanvas());
810 REPORTER_ASSERT(reporter, !recorder.detach());
811
Robert Phillips0a15cc62019-07-30 12:49:10 -0400812 GrBackendFormat format = context->defaultBackendFormat(kRGBA_8888_SkColorType,
813 GrRenderable::kNo);
814 SkASSERT(format.isValid());
Greg Daniel60ea40c2019-02-12 13:38:44 -0500815
Brian Salomonf55e8d52019-01-30 17:28:20 -0500816 sk_sp<SkImage> image = recorder.makePromiseTexture(
817 format, 32, 32, GrMipMapped::kNo,
818 kTopLeft_GrSurfaceOrigin,
819 kRGBA_8888_SkColorType,
820 kPremul_SkAlphaType, nullptr,
821 dummy_fulfill_proc,
822 dummy_release_proc,
823 dummy_done_proc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500824 nullptr,
825 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400826 REPORTER_ASSERT(reporter, !image);
827 }
828
829}
830
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400831////////////////////////////////////////////////////////////////////////////////
Robert Phillips874b5352018-03-16 08:48:24 -0400832// Ensure that flushing while DDL recording doesn't cause a crash
833DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLFlushWhileRecording, reporter, ctxInfo) {
834 GrContext* context = ctxInfo.grContext();
835
836 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
837 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
838
839 SkSurfaceCharacterization characterization;
840 SkAssertResult(s->characterize(&characterization));
841
842 SkDeferredDisplayListRecorder recorder(characterization);
843 SkCanvas* canvas = recorder.getCanvas();
844
Robert Phillips874b5352018-03-16 08:48:24 -0400845 canvas->getGrContext()->flush();
846}
Greg Danielf2336e42018-01-23 16:38:14 -0500847
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400848////////////////////////////////////////////////////////////////////////////////
Robert Phillipsee5fd132019-05-07 13:29:22 -0400849// Test that flushing a DDL via SkSurface::flush works
850
851struct FulfillInfo {
852 sk_sp<SkPromiseImageTexture> fTex;
853 bool fFulfilled = false;
854 bool fReleased = false;
855 bool fDone = false;
856};
857
858static sk_sp<SkPromiseImageTexture> tracking_fulfill_proc(void* context) {
859 FulfillInfo* info = (FulfillInfo*) context;
860 info->fFulfilled = true;
861 return info->fTex;
862}
863
864static void tracking_release_proc(void* context) {
865 FulfillInfo* info = (FulfillInfo*) context;
866 info->fReleased = true;
867}
868
869static void tracking_done_proc(void* context) {
870 FulfillInfo* info = (FulfillInfo*) context;
871 info->fDone = true;
872}
873
874DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSkSurfaceFlush, reporter, ctxInfo) {
875 GrContext* context = ctxInfo.grContext();
876
877 SkImageInfo ii = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
878 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
879
880 SkSurfaceCharacterization characterization;
881 SkAssertResult(s->characterize(&characterization));
882
883 GrBackendTexture backendTexture;
884
Robert Phillips0efc01d2019-11-06 17:19:30 +0000885 if (!CreateBackendTexture(context, &backendTexture, ii, SkColors::kCyan, GrMipMapped::kNo,
886 GrRenderable::kNo)) {
Robert Phillipsee5fd132019-05-07 13:29:22 -0400887 REPORTER_ASSERT(reporter, false);
888 return;
889 }
890
891 FulfillInfo fulfillInfo;
892 fulfillInfo.fTex = SkPromiseImageTexture::Make(backendTexture);
893
894 std::unique_ptr<SkDeferredDisplayList> ddl;
895
896 {
897 SkDeferredDisplayListRecorder recorder(characterization);
898
Robert Phillips0a15cc62019-07-30 12:49:10 -0400899 GrBackendFormat format = context->defaultBackendFormat(kRGBA_8888_SkColorType,
900 GrRenderable::kNo);
901 SkASSERT(format.isValid());
Robert Phillipsee5fd132019-05-07 13:29:22 -0400902
903 sk_sp<SkImage> promiseImage = recorder.makePromiseTexture(
904 format, 32, 32, GrMipMapped::kNo,
905 kTopLeft_GrSurfaceOrigin,
906 kRGBA_8888_SkColorType,
907 kPremul_SkAlphaType, nullptr,
908 tracking_fulfill_proc,
909 tracking_release_proc,
910 tracking_done_proc,
911 &fulfillInfo,
912 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
913
914 SkCanvas* canvas = recorder.getCanvas();
915
916 canvas->clear(SK_ColorRED);
917 canvas->drawImage(promiseImage, 0, 0);
918 ddl = recorder.detach();
919 }
920
Robert Phillips15c91422019-05-07 16:54:48 -0400921 context->flush();
922
Robert Phillipsee5fd132019-05-07 13:29:22 -0400923 s->draw(ddl.get());
924
925 GrFlushInfo flushInfo;
Robert Phillips8e49a692019-05-07 15:57:25 -0400926 s->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
Robert Phillipsee5fd132019-05-07 13:29:22 -0400927
928 REPORTER_ASSERT(reporter, fulfillInfo.fFulfilled);
929 REPORTER_ASSERT(reporter, fulfillInfo.fReleased);
930
Robert Phillips8e49a692019-05-07 15:57:25 -0400931 if (GrBackendApi::kVulkan == context->backend() ||
932 GrBackendApi::kMetal == context->backend()) {
Robert Phillips15c91422019-05-07 16:54:48 -0400933 // In order to receive the done callback with Vulkan we need to perform the equivalent
Robert Phillipsee5fd132019-05-07 13:29:22 -0400934 // of a glFinish
935 GrFlushInfo flushInfoSyncCpu;
936 flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
Robert Phillips8e49a692019-05-07 15:57:25 -0400937 s->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfoSyncCpu);
Robert Phillipsee5fd132019-05-07 13:29:22 -0400938 }
939
940 REPORTER_ASSERT(reporter, fulfillInfo.fDone);
941
942 REPORTER_ASSERT(reporter, fulfillInfo.fTex->unique());
943 fulfillInfo.fTex.reset();
944
Brian Salomon28a8f282019-10-24 20:07:39 -0400945 DeleteBackendTexture(context, backendTexture);
Robert Phillipsee5fd132019-05-07 13:29:22 -0400946}
947
948////////////////////////////////////////////////////////////////////////////////
Robert Phillipsf54883c2018-12-18 08:29:09 -0500949// Ensure that reusing a single DDLRecorder to create multiple DDLs works cleanly
950DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMultipleDDLs, reporter, ctxInfo) {
951 GrContext* context = ctxInfo.grContext();
952
953 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
954 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
955
956 SkBitmap bitmap;
957 bitmap.allocPixels(ii);
958
959 SkSurfaceCharacterization characterization;
960 SkAssertResult(s->characterize(&characterization));
961
962 SkDeferredDisplayListRecorder recorder(characterization);
963
964 SkCanvas* canvas1 = recorder.getCanvas();
965
966 canvas1->clear(SK_ColorRED);
967
968 canvas1->save();
969 canvas1->clipRect(SkRect::MakeXYWH(8, 8, 16, 16));
970
971 std::unique_ptr<SkDeferredDisplayList> ddl1 = recorder.detach();
972
973 SkCanvas* canvas2 = recorder.getCanvas();
974
975 SkPaint p;
976 p.setColor(SK_ColorGREEN);
977 canvas2->drawRect(SkRect::MakeWH(32, 32), p);
978
979 std::unique_ptr<SkDeferredDisplayList> ddl2 = recorder.detach();
980
981 REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData());
982 REPORTER_ASSERT(reporter, ddl2->priv().lazyProxyData());
983
984 // The lazy proxy data being different ensures that the SkSurface, SkCanvas and backing-
985 // lazy proxy are all different between the two DDLs
986 REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData() != ddl2->priv().lazyProxyData());
987
988 s->draw(ddl1.get());
989 s->draw(ddl2.get());
990
991 // Make sure the clipRect from DDL1 didn't percolate into DDL2
992 s->readPixels(ii, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
993 for (int y = 0; y < 32; ++y) {
994 for (int x = 0; x < 32; ++x) {
995 REPORTER_ASSERT(reporter, bitmap.getColor(x, y) == SK_ColorGREEN);
996 if (bitmap.getColor(x, y) != SK_ColorGREEN) {
997 return; // we only really need to report the error once
998 }
999 }
1000 }
1001}
1002
John Rosascoa9b348f2019-11-08 13:18:15 -08001003#ifdef SK_GL
Robert Phillipsf54883c2018-12-18 08:29:09 -05001004////////////////////////////////////////////////////////////////////////////////
Robert Phillipsabf7b762018-03-21 12:13:37 -04001005// Check that the texture-specific flags (i.e., for external & rectangle textures) work
1006// for promise images. As such, this is a GL-only test.
1007DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLTextureFlagsTest, reporter, ctxInfo) {
1008 GrContext* context = ctxInfo.grContext();
1009
1010 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
1011 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
1012
1013 SkSurfaceCharacterization characterization;
1014 SkAssertResult(s->characterize(&characterization));
1015
1016 SkDeferredDisplayListRecorder recorder(characterization);
1017
1018 for (GrGLenum target : { GR_GL_TEXTURE_EXTERNAL, GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_2D } ) {
Greg Daniel09c94002018-06-08 22:11:51 +00001019 for (auto mipMapped : { GrMipMapped::kNo, GrMipMapped::kYes }) {
1020 GrBackendFormat format = GrBackendFormat::MakeGL(GR_GL_RGBA8, target);
Robert Phillipsabf7b762018-03-21 12:13:37 -04001021
Brian Salomonf55e8d52019-01-30 17:28:20 -05001022 sk_sp<SkImage> image = recorder.makePromiseTexture(
1023 format, 32, 32, mipMapped,
1024 kTopLeft_GrSurfaceOrigin,
1025 kRGBA_8888_SkColorType,
1026 kPremul_SkAlphaType, nullptr,
1027 dummy_fulfill_proc,
1028 dummy_release_proc,
1029 dummy_done_proc,
Brian Salomon0cc57542019-03-08 13:28:46 -05001030 nullptr,
1031 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
Greg Daniel09c94002018-06-08 22:11:51 +00001032 if (GR_GL_TEXTURE_2D != target && mipMapped == GrMipMapped::kYes) {
1033 REPORTER_ASSERT(reporter, !image);
1034 continue;
1035 }
1036 REPORTER_ASSERT(reporter, image);
Robert Phillipsabf7b762018-03-21 12:13:37 -04001037
Jim Van Verth21bd60d2018-10-12 15:00:20 -04001038 GrTextureProxy* backingProxy = ((SkImage_GpuBase*) image.get())->peekProxy();
Robert Phillipsabf7b762018-03-21 12:13:37 -04001039
Greg Daniel09c94002018-06-08 22:11:51 +00001040 REPORTER_ASSERT(reporter, backingProxy->mipMapped() == mipMapped);
1041 if (GR_GL_TEXTURE_2D == target) {
Brian Salomonfd98c2c2018-07-31 17:25:29 -04001042 REPORTER_ASSERT(reporter, !backingProxy->hasRestrictedSampling());
Greg Daniel09c94002018-06-08 22:11:51 +00001043 } else {
Brian Salomonfd98c2c2018-07-31 17:25:29 -04001044 REPORTER_ASSERT(reporter, backingProxy->hasRestrictedSampling());
Greg Daniel09c94002018-06-08 22:11:51 +00001045 }
Robert Phillipsabf7b762018-03-21 12:13:37 -04001046 }
1047 }
Robert Phillipsbe77a022018-04-03 17:17:05 -04001048}
John Rosascoa9b348f2019-11-08 13:18:15 -08001049#endif // SK_GL
Robert Phillipsbe77a022018-04-03 17:17:05 -04001050
1051////////////////////////////////////////////////////////////////////////////////
Robert Phillips646f6372018-09-25 09:31:10 -04001052// Test colorType and pixelConfig compatibility.
Robert Phillipsbe77a022018-04-03 17:17:05 -04001053DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLCompatibilityTest, reporter, ctxInfo) {
1054 GrContext* context = ctxInfo.grContext();
1055
1056 for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
1057 SkColorType colorType = static_cast<SkColorType>(ct);
1058
Robert Phillips3cd54322019-07-10 09:28:59 -04001059 SurfaceParameters params(context);
Greg Daniel60ea40c2019-02-12 13:38:44 -05001060 params.setColorType(colorType);
1061 params.setColorSpace(nullptr);
Robert Phillipsbe77a022018-04-03 17:17:05 -04001062
Brian Salomon4687bdd2019-05-09 16:28:04 -04001063 if (!context->priv().caps()->mipMapSupport()) {
1064 params.setShouldCreateMipMaps(false);
1065 }
Greg Daniel60ea40c2019-02-12 13:38:44 -05001066
Robert Phillipsd8f79a22019-06-24 13:25:42 -04001067 test_make_render_target(reporter, context, params);
Robert Phillipsbe77a022018-04-03 17:17:05 -04001068 }
Robert Phillipsabf7b762018-03-21 12:13:37 -04001069
1070}