blob: 5012b672d4744ab9ae50c7626af00636410bda8a [file] [log] [blame]
Robert Phillips7ffbcf92017-12-04 12:52:46 -05001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkBitmap.h"
9#include "include/core/SkCanvas.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040010#include "include/core/SkColor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkColorSpace.h"
Robert Phillipsad3b2c92020-02-21 10:18:00 -050012#include "include/core/SkDeferredDisplayList.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkDeferredDisplayListRecorder.h"
14#include "include/core/SkImage.h"
15#include "include/core/SkImageInfo.h"
16#include "include/core/SkPaint.h"
17#include "include/core/SkPromiseImageTexture.h"
18#include "include/core/SkRect.h"
19#include "include/core/SkRefCnt.h"
20#include "include/core/SkSurface.h"
21#include "include/core/SkSurfaceCharacterization.h"
22#include "include/core/SkSurfaceProps.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040023#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "include/gpu/GrBackendSurface.h"
25#include "include/gpu/GrContext.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040026#include "include/gpu/GrContextThreadSafeProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "include/gpu/GrTypes.h"
28#include "include/gpu/gl/GrGLTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050029#include "include/private/GrTypesPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050030#include "src/core/SkDeferredDisplayListPriv.h"
31#include "src/gpu/GrCaps.h"
32#include "src/gpu/GrContextPriv.h"
33#include "src/gpu/GrGpu.h"
34#include "src/gpu/GrRenderTargetContext.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040035#include "src/gpu/GrRenderTargetProxy.h"
36#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050037#include "src/gpu/SkGpuDevice.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050038#include "src/gpu/gl/GrGLDefines.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040039#include "src/image/SkImage_GpuBase.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050040#include "src/image/SkSurface_Gpu.h"
41#include "tests/Test.h"
Robert Phillipsee5fd132019-05-07 13:29:22 -040042#include "tests/TestUtils.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050043#include "tools/gpu/GrContextFactory.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040044
45#include <initializer_list>
46#include <memory>
47#include <utility>
Robert Phillipsfc711a22018-02-13 17:03:00 -050048
Robert Phillips3cd54322019-07-10 09:28:59 -040049#ifdef SK_VULKAN
50#include "src/gpu/vk/GrVkCaps.h"
51#endif
52
Robert Phillips7ffbcf92017-12-04 12:52:46 -050053class SurfaceParameters {
54public:
Robert Phillips3cd54322019-07-10 09:28:59 -040055 static const int kNumParams = 12;
56 static const int kSampleCount = 5;
57 static const int kMipMipCount = 8;
58 static const int kFBO0Count = 9;
59 static const int kProtectedCount = 11;
Robert Phillips7ffbcf92017-12-04 12:52:46 -050060
Robert Phillips3cd54322019-07-10 09:28:59 -040061 SurfaceParameters(GrContext* context)
62 : fBackend(context->backend())
Robert Phillipsb45f47d2019-02-03 17:17:54 -050063 , fWidth(64)
Robert Phillips7ffbcf92017-12-04 12:52:46 -050064 , fHeight(64)
65 , fOrigin(kTopLeft_GrSurfaceOrigin)
66 , fColorType(kRGBA_8888_SkColorType)
67 , fColorSpace(SkColorSpace::MakeSRGB())
Brian Salomonbdecacf2018-02-02 20:32:49 -050068 , fSampleCount(1)
Robert Phillipse8fabb22018-02-04 14:33:21 -050069 , fSurfaceProps(0x0, kUnknown_SkPixelGeometry)
Robert Phillipsb45f47d2019-02-03 17:17:54 -050070 , fShouldCreateMipMaps(true)
71 , fUsesGLFBO0(false)
Robert Phillips3cd54322019-07-10 09:28:59 -040072 , fIsTextureable(true)
73 , fIsProtected(GrProtected::kNo) {
74#ifdef SK_VULKAN
75 if (GrBackendApi::kVulkan == context->backend()) {
76 const GrVkCaps* vkCaps = (const GrVkCaps*) context->priv().caps();
77
78 fIsProtected = GrProtected(vkCaps->supportsProtectedMemory());
79 }
80#endif
Robert Phillipse8fabb22018-02-04 14:33:21 -050081 }
Robert Phillips7ffbcf92017-12-04 12:52:46 -050082
83 int sampleCount() const { return fSampleCount; }
84
Robert Phillipsbe77a022018-04-03 17:17:05 -040085 void setColorType(SkColorType ct) { fColorType = ct; }
Robert Phillipsd8f79a22019-06-24 13:25:42 -040086 SkColorType colorType() const { return fColorType; }
Robert Phillipsbe77a022018-04-03 17:17:05 -040087 void setColorSpace(sk_sp<SkColorSpace> cs) { fColorSpace = std::move(cs); }
Robert Phillipsb45f47d2019-02-03 17:17:54 -050088 void setTextureable(bool isTextureable) { fIsTextureable = isTextureable; }
Brian Salomon4687bdd2019-05-09 16:28:04 -040089 void setShouldCreateMipMaps(bool shouldCreateMipMaps) {
90 fShouldCreateMipMaps = shouldCreateMipMaps;
91 }
Robert Phillipsbe77a022018-04-03 17:17:05 -040092
Robert Phillips7ffbcf92017-12-04 12:52:46 -050093 // Modify the SurfaceParameters in just one way
94 void modify(int i) {
95 switch (i) {
96 case 0:
97 fWidth = 63;
98 break;
99 case 1:
100 fHeight = 63;
101 break;
102 case 2:
103 fOrigin = kBottomLeft_GrSurfaceOrigin;
104 break;
105 case 3:
106 fColorType = kRGBA_F16_SkColorType;
107 break;
108 case 4:
Brian Osman37f99882018-08-09 10:26:57 -0400109 // This just needs to be a colorSpace different from that returned by MakeSRGB().
110 // In this case we just change the gamut.
Brian Osman82ebe042019-01-04 17:03:00 -0500111 fColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kAdobeRGB);
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500112 break;
113 case kSampleCount:
114 fSampleCount = 4;
115 break;
116 case 6:
117 fSurfaceProps = SkSurfaceProps(0x0, kRGB_H_SkPixelGeometry);
118 break;
119 case 7:
120 fSurfaceProps = SkSurfaceProps(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
121 kUnknown_SkPixelGeometry);
122 break;
Robert Phillipse8fabb22018-02-04 14:33:21 -0500123 case 8:
124 fShouldCreateMipMaps = false;
125 break;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500126 case 9:
127 if (GrBackendApi::kOpenGL == fBackend) {
128 fUsesGLFBO0 = true;
Robert Phillipsc046ff02019-07-01 10:34:03 -0400129 fShouldCreateMipMaps = false; // needs to changed in tandem w/ textureability
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500130 fIsTextureable = false;
131 }
132 break;
133 case 10:
Robert Phillipsc046ff02019-07-01 10:34:03 -0400134 fShouldCreateMipMaps = false; // needs to changed in tandem w/ textureability
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500135 fIsTextureable = false;
136 break;
Robert Phillips3cd54322019-07-10 09:28:59 -0400137 case 11:
138 fIsProtected = GrProtected::kYes == fIsProtected ? GrProtected::kNo
139 : GrProtected::kYes;
140 break;
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500141 }
142 }
143
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400144 SkSurfaceCharacterization createCharacterization(GrContext* context) const {
Robert Phillipscf39f372019-09-03 10:29:20 -0400145 size_t maxResourceBytes = context->getResourceCacheLimit();
Robert Phillipsfc711a22018-02-13 17:03:00 -0500146
Robert Phillipsd470e1b2019-09-04 15:05:35 -0400147 if (!context->colorTypeSupportedAsSurface(fColorType)) {
148 return SkSurfaceCharacterization();
149 }
150
Robert Phillipsfc711a22018-02-13 17:03:00 -0500151 // Note that Ganesh doesn't make use of the SkImageInfo's alphaType
152 SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType,
153 kPremul_SkAlphaType, fColorSpace);
154
Robert Phillips0a15cc62019-07-30 12:49:10 -0400155 GrBackendFormat backendFormat = context->defaultBackendFormat(fColorType,
156 GrRenderable::kYes);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400157 if (!backendFormat.isValid()) {
158 return SkSurfaceCharacterization();
159 }
Robert Phillipsfc711a22018-02-13 17:03:00 -0500160
161 SkSurfaceCharacterization c = context->threadSafeProxy()->createCharacterization(
162 maxResourceBytes, ii, backendFormat, fSampleCount,
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500163 fOrigin, fSurfaceProps, fShouldCreateMipMaps,
Robert Phillips3cd54322019-07-10 09:28:59 -0400164 fUsesGLFBO0, fIsTextureable, fIsProtected);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400165 return c;
166 }
167
168 // Create a DDL whose characterization captures the current settings
169 std::unique_ptr<SkDeferredDisplayList> createDDL(GrContext* context) const {
170 SkSurfaceCharacterization c = this->createCharacterization(context);
Robert Phillipsfc711a22018-02-13 17:03:00 -0500171 SkAssertResult(c.isValid());
Robert Phillipse8fabb22018-02-04 14:33:21 -0500172
173 SkDeferredDisplayListRecorder r(c);
174 SkCanvas* canvas = r.getCanvas();
175 if (!canvas) {
176 return nullptr;
177 }
178
179 canvas->drawRect(SkRect::MakeXYWH(10, 10, 10, 10), SkPaint());
180 return r.detach();
181 }
182
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500183 // Create the surface with the current set of parameters
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500184 sk_sp<SkSurface> make(GrContext* context, GrBackendTexture* backend) const {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400185 const SkSurfaceCharacterization c = this->createCharacterization(context);
186
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500187 GrMipMapped mipmapped = !fIsTextureable
Robert Phillipsbe77a022018-04-03 17:17:05 -0400188 ? GrMipMapped::kNo
189 : GrMipMapped(fShouldCreateMipMaps);
Robert Phillipse8fabb22018-02-04 14:33:21 -0500190
John Rosasco24cbdab2019-09-25 14:14:35 -0700191#ifdef SK_GL
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500192 if (fUsesGLFBO0) {
193 if (GrBackendApi::kOpenGL != context->backend()) {
194 return nullptr;
195 }
196
197 GrGLFramebufferInfo fboInfo;
198 fboInfo.fFBOID = 0;
199 fboInfo.fFormat = GR_GL_RGBA8;
200 static constexpr int kStencilBits = 8;
201 GrBackendRenderTarget backendRT(fWidth, fHeight, 1, kStencilBits, fboInfo);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500202
203 if (!backendRT.isValid()) {
204 return nullptr;
205 }
206
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400207 sk_sp<SkSurface> result = SkSurface::MakeFromBackendRenderTarget(context, backendRT,
208 fOrigin, fColorType,
209 fColorSpace,
210 &fSurfaceProps);
Robert Phillips9907e6e2019-06-25 14:47:04 -0400211 SkASSERT(result->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400212 return result;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500213 }
John Rosasco24cbdab2019-09-25 14:14:35 -0700214#endif
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 Phillipsb3c061a2020-02-13 13:24:47 -0500550
551 // Exercise the createBackendFormat method
552 {
553 SurfaceParameters params(context);
554 GrBackendTexture backend;
555
556 sk_sp<SkSurface> s = params.make(context, &backend);
557 if (!s) {
558 return;
559 }
560
561 SkSurfaceCharacterization char0;
562 SkAssertResult(s->characterize(&char0));
563
564 // The default params create a renderable RGBA8 surface
565 auto originalBackendFormat = context->defaultBackendFormat(kRGBA_8888_SkColorType,
566 GrRenderable::kYes);
567 REPORTER_ASSERT(reporter, originalBackendFormat.isValid());
568 REPORTER_ASSERT(reporter, char0.backendFormat() == originalBackendFormat);
569
570 auto newBackendFormat = context->defaultBackendFormat(kRGB_565_SkColorType,
571 GrRenderable::kYes);
572
573 if (newBackendFormat.isValid()) {
574 SkSurfaceCharacterization char1 = char0.createBackendFormat(kRGB_565_SkColorType,
575 newBackendFormat);
576 REPORTER_ASSERT(reporter, char1.isValid());
577 REPORTER_ASSERT(reporter, char1.backendFormat() == newBackendFormat);
578
579 SkSurfaceCharacterization invalid;
580 REPORTER_ASSERT(reporter, !invalid.isValid());
581 auto stillInvalid = invalid.createBackendFormat(kRGB_565_SkColorType,
582 newBackendFormat);
583 REPORTER_ASSERT(reporter, !stillInvalid.isValid());
584 }
585
586 s = nullptr;
587 params.cleanUpBackEnd(context, backend);
588 }
589
590 // Exercise the createFBO0 method
591 if (context->backend() == GrBackendApi::kOpenGL) {
592 SurfaceParameters params(context);
593 GrBackendTexture backend;
594
595 sk_sp<SkSurface> s = params.make(context, &backend);
596 if (!s) {
597 return;
598 }
599
600 SkSurfaceCharacterization char0;
601 SkAssertResult(s->characterize(&char0));
602
603 // The default params create a non-FBO0 surface
604 REPORTER_ASSERT(reporter, !char0.usesGLFBO0());
605
606 {
607 SkSurfaceCharacterization char1 = char0.createFBO0(true);
608 REPORTER_ASSERT(reporter, char1.isValid());
609 REPORTER_ASSERT(reporter, char1.usesGLFBO0());
610 }
611
612 {
613 SkSurfaceCharacterization invalid;
614 REPORTER_ASSERT(reporter, !invalid.isValid());
615 SkSurfaceCharacterization stillInvalid = invalid.createFBO0(true);
616 REPORTER_ASSERT(reporter, !stillInvalid.isValid());
617 }
618
619 s = nullptr;
620 params.cleanUpBackEnd(context, backend);
621 }
Robert Phillips7ffbcf92017-12-04 12:52:46 -0500622}
623
Robert Phillips3cd54322019-07-10 09:28:59 -0400624DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo) {
625 GrContext* context = ctxInfo.grContext();
626
627 DDLSurfaceCharacterizationTestImpl(context, reporter);
628}
629
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500630// Test that a DDL created w/o textureability can be replayed into both a textureable and
631// non-textureable destination. Note that DDLSurfaceCharacterizationTest tests that a
632// textureable DDL cannot be played into a non-textureable destination but can be replayed
633// into a textureable destination.
634DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLNonTextureabilityTest, reporter, ctxInfo) {
635 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500636 GrGpu* gpu = context->priv().getGpu();
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500637
638 // Create a bitmap that we can readback into
639 SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
640 kPremul_SkAlphaType);
641 SkBitmap bitmap;
642 bitmap.allocPixels(imageInfo);
643
644 for (bool textureability : { true, false }) {
645 std::unique_ptr<SkDeferredDisplayList> ddl;
646
Robert Phillipsc046ff02019-07-01 10:34:03 -0400647 // First, create a DDL w/o textureability (and thus no mipmaps). TODO: once we have
648 // reusable DDLs, move this outside of the loop.
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500649 {
Robert Phillips3cd54322019-07-10 09:28:59 -0400650 SurfaceParameters params(context);
Robert Phillipsc046ff02019-07-01 10:34:03 -0400651 params.setShouldCreateMipMaps(false);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500652 params.setTextureable(false);
653
654 ddl = params.createDDL(context);
655 SkAssertResult(ddl);
656 }
657
658 // Then verify it can draw into either flavor of destination
Robert Phillips3cd54322019-07-10 09:28:59 -0400659 SurfaceParameters params(context);
Robert Phillipsc046ff02019-07-01 10:34:03 -0400660 params.setShouldCreateMipMaps(textureability);
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500661 params.setTextureable(textureability);
662
663 GrBackendTexture backend;
664 sk_sp<SkSurface> s = params.make(context, &backend);
665 if (!s) {
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500666 continue;
667 }
668
669 REPORTER_ASSERT(reporter, s->draw(ddl.get()));
670 s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
671 context->flush();
672 gpu->testingOnly_flushGpuAndSync();
673 s = nullptr;
674 params.cleanUpBackEnd(context, backend);
675 }
676
677}
678
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400679static void test_make_render_target(skiatest::Reporter* reporter,
680 GrContext* context,
681 const SurfaceParameters& params) {
682 {
683 const SkSurfaceCharacterization c = params.createCharacterization(context);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400684
Robert Phillipsbe77a022018-04-03 17:17:05 -0400685 if (!c.isValid()) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400686 GrBackendTexture backend;
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500687 sk_sp<SkSurface> tmp = params.make(context, &backend);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400688
689 // If we couldn't characterize the surface we shouldn't be able to create it either
690 REPORTER_ASSERT(reporter, !tmp);
691 if (tmp) {
692 tmp = nullptr;
693 params.cleanUpBackEnd(context, backend);
694 }
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400695 return;
696 }
697 }
698
699 const SkSurfaceCharacterization c = params.createCharacterization(context);
700 GrBackendTexture backend;
701
702 {
703 sk_sp<SkSurface> s = params.make(context, &backend);
704 REPORTER_ASSERT(reporter, s);
705 if (!s) {
706 REPORTER_ASSERT(reporter, !c.isValid());
707 params.cleanUpBackEnd(context, backend);
708 return;
709 }
710
711 REPORTER_ASSERT(reporter, c.isValid());
Robert Phillipsc046ff02019-07-01 10:34:03 -0400712 REPORTER_ASSERT(reporter, c.isCompatible(backend));
Robert Phillips9907e6e2019-06-25 14:47:04 -0400713 REPORTER_ASSERT(reporter, s->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400714 // Note that we're leaving 'backend' live here
715 }
716
717 // Make an SkSurface from scratch
718 {
719 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, c, SkBudgeted::kYes);
720 REPORTER_ASSERT(reporter, s);
Robert Phillips9907e6e2019-06-25 14:47:04 -0400721 REPORTER_ASSERT(reporter, s->isCompatible(c));
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400722 }
723
Robert Phillips02dc0302019-07-02 17:58:27 -0400724 // Make an SkSurface that wraps the existing backend texture
725 {
726 sk_sp<SkSurface> s = SkSurface::MakeFromBackendTexture(context, c, backend);
727 REPORTER_ASSERT(reporter, s);
728 REPORTER_ASSERT(reporter, s->isCompatible(c));
729 }
730
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400731 params.cleanUpBackEnd(context, backend);
732}
733
734////////////////////////////////////////////////////////////////////////////////
735// This tests the SkSurface::MakeRenderTarget variants that take an SkSurfaceCharacterization.
736// In particular, the SkSurface, backendTexture and SkSurfaceCharacterization
737// should always be compatible.
Robert Phillips3cd54322019-07-10 09:28:59 -0400738void DDLMakeRenderTargetTestImpl(GrContext* context, skiatest::Reporter* reporter) {
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400739 for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
740
741 if (SurfaceParameters::kFBO0Count == i) {
742 // MakeRenderTarget doesn't support FBO0
Robert Phillipsbe77a022018-04-03 17:17:05 -0400743 continue;
744 }
745
Robert Phillips3cd54322019-07-10 09:28:59 -0400746 if (SurfaceParameters::kProtectedCount == i) {
747 if (context->backend() != GrBackendApi::kVulkan) {
748 // Only the Vulkan backend respects the protected parameter
749 continue;
750 }
751#ifdef SK_VULKAN
752 const GrVkCaps* vkCaps = (const GrVkCaps*) context->priv().caps();
753
754 // And, even then, only when it is a protected context
755 if (!vkCaps->supportsProtectedMemory()) {
756 continue;
757 }
758#endif
759 }
760
761
762 SurfaceParameters params(context);
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400763 params.modify(i);
764
Brian Salomon4687bdd2019-05-09 16:28:04 -0400765 if (!context->priv().caps()->mipMapSupport()) {
766 params.setShouldCreateMipMaps(false);
767 }
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400768
Robert Phillipsd8f79a22019-06-24 13:25:42 -0400769 test_make_render_target(reporter, context, params);
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400770 }
771}
772
Robert Phillips3cd54322019-07-10 09:28:59 -0400773DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMakeRenderTargetTest, reporter, ctxInfo) {
774 GrContext* context = ctxInfo.grContext();
775
776 DDLMakeRenderTargetTestImpl(context, reporter);
777}
778
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400779////////////////////////////////////////////////////////////////////////////////
Greg Danielf2336e42018-01-23 16:38:14 -0500780static constexpr int kSize = 8;
781
782struct TextureReleaseChecker {
783 TextureReleaseChecker() : fReleaseCount(0) {}
784 int fReleaseCount;
785 static void Release(void* self) {
786 static_cast<TextureReleaseChecker*>(self)->fReleaseCount++;
787 }
788};
789
790enum class DDLStage { kMakeImage, kDrawImage, kDetach, kDrawDDL };
791
792// This tests the ability to create and use wrapped textures in a DDL world
793DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
794 GrContext* context = ctxInfo.grContext();
Robert Phillips9b16f812019-05-17 10:01:21 -0400795
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400796 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400797 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400798 SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
Brian Salomonf7778972018-03-08 10:13:17 -0500799 if (!backendTex.isValid()) {
800 return;
Greg Danielf2336e42018-01-23 16:38:14 -0500801 }
Brian Salomonf7778972018-03-08 10:13:17 -0500802
Robert Phillips3cd54322019-07-10 09:28:59 -0400803 SurfaceParameters params(context);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400804 GrBackendTexture backend;
Brian Salomonf7778972018-03-08 10:13:17 -0500805
Robert Phillipsb45f47d2019-02-03 17:17:54 -0500806 sk_sp<SkSurface> s = params.make(context, &backend);
Brian Salomonf7778972018-03-08 10:13:17 -0500807 if (!s) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400808 context->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500809 return;
810 }
811
812 SkSurfaceCharacterization c;
813 SkAssertResult(s->characterize(&c));
814
815 std::unique_ptr<SkDeferredDisplayListRecorder> recorder(new SkDeferredDisplayListRecorder(c));
816
817 SkCanvas* canvas = recorder->getCanvas();
818 if (!canvas) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400819 s = nullptr;
820 params.cleanUpBackEnd(context, backend);
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400821 context->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500822 return;
823 }
824
825 GrContext* deferredContext = canvas->getGrContext();
826 if (!deferredContext) {
Robert Phillipsbe77a022018-04-03 17:17:05 -0400827 s = nullptr;
828 params.cleanUpBackEnd(context, backend);
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400829 context->deleteBackendTexture(backendTex);
Brian Salomonf7778972018-03-08 10:13:17 -0500830 return;
831 }
832
833 // Wrapped Backend Textures are not supported in DDL
834 sk_sp<SkImage> image =
835 SkImage::MakeFromAdoptedTexture(deferredContext, backendTex, kTopLeft_GrSurfaceOrigin,
836 kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
837 REPORTER_ASSERT(reporter, !image);
838
839 TextureReleaseChecker releaseChecker;
840 image = SkImage::MakeFromTexture(deferredContext, backendTex, kTopLeft_GrSurfaceOrigin,
841 kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr,
842 TextureReleaseChecker::Release, &releaseChecker);
843 REPORTER_ASSERT(reporter, !image);
844
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400845 context->deleteBackendTexture(backendTex);
Robert Phillipsbe77a022018-04-03 17:17:05 -0400846
847 s = nullptr;
848 params.cleanUpBackEnd(context, backend);
Greg Danielf2336e42018-01-23 16:38:14 -0500849}
850
Brian Salomon59ef8c32019-01-30 12:20:56 -0500851static sk_sp<SkPromiseImageTexture> dummy_fulfill_proc(void*) {
852 SkASSERT(0);
853 return nullptr;
854}
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400855static void dummy_release_proc(void*) { SkASSERT(0); }
Brian Salomon59ef8c32019-01-30 12:20:56 -0500856static void dummy_done_proc(void*) {}
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400857
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400858////////////////////////////////////////////////////////////////////////////////
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400859// Test out the behavior of an invalid DDLRecorder
860DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLInvalidRecorder, reporter, ctxInfo) {
861 GrContext* context = ctxInfo.grContext();
862
863 {
864 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
865 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
866
867 SkSurfaceCharacterization characterization;
868 SkAssertResult(s->characterize(&characterization));
869
870 // never calling getCanvas means the backing surface is never allocated
871 SkDeferredDisplayListRecorder recorder(characterization);
872 }
873
874 {
875 SkSurfaceCharacterization invalid;
876
877 SkDeferredDisplayListRecorder recorder(invalid);
878
879 const SkSurfaceCharacterization c = recorder.characterization();
880 REPORTER_ASSERT(reporter, !c.isValid());
881 REPORTER_ASSERT(reporter, !recorder.getCanvas());
882 REPORTER_ASSERT(reporter, !recorder.detach());
883
Robert Phillips0a15cc62019-07-30 12:49:10 -0400884 GrBackendFormat format = context->defaultBackendFormat(kRGBA_8888_SkColorType,
885 GrRenderable::kNo);
886 SkASSERT(format.isValid());
Greg Daniel60ea40c2019-02-12 13:38:44 -0500887
Brian Salomonf55e8d52019-01-30 17:28:20 -0500888 sk_sp<SkImage> image = recorder.makePromiseTexture(
889 format, 32, 32, GrMipMapped::kNo,
890 kTopLeft_GrSurfaceOrigin,
891 kRGBA_8888_SkColorType,
892 kPremul_SkAlphaType, nullptr,
893 dummy_fulfill_proc,
894 dummy_release_proc,
895 dummy_done_proc,
Brian Salomon0cc57542019-03-08 13:28:46 -0500896 nullptr,
897 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
Robert Phillips6ceaafa2018-03-15 16:53:06 -0400898 REPORTER_ASSERT(reporter, !image);
899 }
900
901}
902
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400903////////////////////////////////////////////////////////////////////////////////
Robert Phillips874b5352018-03-16 08:48:24 -0400904// Ensure that flushing while DDL recording doesn't cause a crash
905DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLFlushWhileRecording, reporter, ctxInfo) {
906 GrContext* context = ctxInfo.grContext();
907
908 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
909 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
910
911 SkSurfaceCharacterization characterization;
912 SkAssertResult(s->characterize(&characterization));
913
914 SkDeferredDisplayListRecorder recorder(characterization);
915 SkCanvas* canvas = recorder.getCanvas();
916
Robert Phillips874b5352018-03-16 08:48:24 -0400917 canvas->getGrContext()->flush();
918}
Greg Danielf2336e42018-01-23 16:38:14 -0500919
Robert Phillips6b6fcc72018-03-30 13:57:00 -0400920////////////////////////////////////////////////////////////////////////////////
Robert Phillipsee5fd132019-05-07 13:29:22 -0400921// Test that flushing a DDL via SkSurface::flush works
922
923struct FulfillInfo {
924 sk_sp<SkPromiseImageTexture> fTex;
925 bool fFulfilled = false;
926 bool fReleased = false;
927 bool fDone = false;
928};
929
930static sk_sp<SkPromiseImageTexture> tracking_fulfill_proc(void* context) {
931 FulfillInfo* info = (FulfillInfo*) context;
932 info->fFulfilled = true;
933 return info->fTex;
934}
935
936static void tracking_release_proc(void* context) {
937 FulfillInfo* info = (FulfillInfo*) context;
938 info->fReleased = true;
939}
940
941static void tracking_done_proc(void* context) {
942 FulfillInfo* info = (FulfillInfo*) context;
943 info->fDone = true;
944}
945
946DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSkSurfaceFlush, reporter, ctxInfo) {
947 GrContext* context = ctxInfo.grContext();
948
949 SkImageInfo ii = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
950 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
951
952 SkSurfaceCharacterization characterization;
953 SkAssertResult(s->characterize(&characterization));
954
955 GrBackendTexture backendTexture;
956
Robert Phillips0efc01d2019-11-06 17:19:30 +0000957 if (!CreateBackendTexture(context, &backendTexture, ii, SkColors::kCyan, GrMipMapped::kNo,
958 GrRenderable::kNo)) {
Robert Phillipsee5fd132019-05-07 13:29:22 -0400959 REPORTER_ASSERT(reporter, false);
960 return;
961 }
962
963 FulfillInfo fulfillInfo;
964 fulfillInfo.fTex = SkPromiseImageTexture::Make(backendTexture);
965
966 std::unique_ptr<SkDeferredDisplayList> ddl;
967
968 {
969 SkDeferredDisplayListRecorder recorder(characterization);
970
Robert Phillips0a15cc62019-07-30 12:49:10 -0400971 GrBackendFormat format = context->defaultBackendFormat(kRGBA_8888_SkColorType,
972 GrRenderable::kNo);
973 SkASSERT(format.isValid());
Robert Phillipsee5fd132019-05-07 13:29:22 -0400974
975 sk_sp<SkImage> promiseImage = recorder.makePromiseTexture(
976 format, 32, 32, GrMipMapped::kNo,
977 kTopLeft_GrSurfaceOrigin,
978 kRGBA_8888_SkColorType,
979 kPremul_SkAlphaType, nullptr,
980 tracking_fulfill_proc,
981 tracking_release_proc,
982 tracking_done_proc,
983 &fulfillInfo,
984 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
985
986 SkCanvas* canvas = recorder.getCanvas();
987
988 canvas->clear(SK_ColorRED);
989 canvas->drawImage(promiseImage, 0, 0);
990 ddl = recorder.detach();
991 }
992
Robert Phillips15c91422019-05-07 16:54:48 -0400993 context->flush();
994
Robert Phillipsee5fd132019-05-07 13:29:22 -0400995 s->draw(ddl.get());
996
997 GrFlushInfo flushInfo;
Robert Phillips8e49a692019-05-07 15:57:25 -0400998 s->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
Robert Phillipsee5fd132019-05-07 13:29:22 -0400999
1000 REPORTER_ASSERT(reporter, fulfillInfo.fFulfilled);
1001 REPORTER_ASSERT(reporter, fulfillInfo.fReleased);
1002
Robert Phillips8e49a692019-05-07 15:57:25 -04001003 if (GrBackendApi::kVulkan == context->backend() ||
1004 GrBackendApi::kMetal == context->backend()) {
Robert Phillips15c91422019-05-07 16:54:48 -04001005 // In order to receive the done callback with Vulkan we need to perform the equivalent
Robert Phillipsee5fd132019-05-07 13:29:22 -04001006 // of a glFinish
1007 GrFlushInfo flushInfoSyncCpu;
1008 flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
Robert Phillips8e49a692019-05-07 15:57:25 -04001009 s->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfoSyncCpu);
Robert Phillipsee5fd132019-05-07 13:29:22 -04001010 }
1011
1012 REPORTER_ASSERT(reporter, fulfillInfo.fDone);
1013
1014 REPORTER_ASSERT(reporter, fulfillInfo.fTex->unique());
1015 fulfillInfo.fTex.reset();
1016
Brian Salomon28a8f282019-10-24 20:07:39 -04001017 DeleteBackendTexture(context, backendTexture);
Robert Phillipsee5fd132019-05-07 13:29:22 -04001018}
1019
1020////////////////////////////////////////////////////////////////////////////////
Robert Phillipsf54883c2018-12-18 08:29:09 -05001021// Ensure that reusing a single DDLRecorder to create multiple DDLs works cleanly
1022DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMultipleDDLs, reporter, ctxInfo) {
1023 GrContext* context = ctxInfo.grContext();
1024
1025 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
1026 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
1027
1028 SkBitmap bitmap;
1029 bitmap.allocPixels(ii);
1030
1031 SkSurfaceCharacterization characterization;
1032 SkAssertResult(s->characterize(&characterization));
1033
1034 SkDeferredDisplayListRecorder recorder(characterization);
1035
1036 SkCanvas* canvas1 = recorder.getCanvas();
1037
1038 canvas1->clear(SK_ColorRED);
1039
1040 canvas1->save();
1041 canvas1->clipRect(SkRect::MakeXYWH(8, 8, 16, 16));
1042
1043 std::unique_ptr<SkDeferredDisplayList> ddl1 = recorder.detach();
1044
1045 SkCanvas* canvas2 = recorder.getCanvas();
1046
1047 SkPaint p;
1048 p.setColor(SK_ColorGREEN);
1049 canvas2->drawRect(SkRect::MakeWH(32, 32), p);
1050
1051 std::unique_ptr<SkDeferredDisplayList> ddl2 = recorder.detach();
1052
1053 REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData());
1054 REPORTER_ASSERT(reporter, ddl2->priv().lazyProxyData());
1055
1056 // The lazy proxy data being different ensures that the SkSurface, SkCanvas and backing-
1057 // lazy proxy are all different between the two DDLs
1058 REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData() != ddl2->priv().lazyProxyData());
1059
1060 s->draw(ddl1.get());
1061 s->draw(ddl2.get());
1062
1063 // Make sure the clipRect from DDL1 didn't percolate into DDL2
1064 s->readPixels(ii, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
1065 for (int y = 0; y < 32; ++y) {
1066 for (int x = 0; x < 32; ++x) {
1067 REPORTER_ASSERT(reporter, bitmap.getColor(x, y) == SK_ColorGREEN);
1068 if (bitmap.getColor(x, y) != SK_ColorGREEN) {
1069 return; // we only really need to report the error once
1070 }
1071 }
1072 }
1073}
1074
John Rosascoa9b348f2019-11-08 13:18:15 -08001075#ifdef SK_GL
Robert Phillipsf54883c2018-12-18 08:29:09 -05001076////////////////////////////////////////////////////////////////////////////////
Robert Phillipsabf7b762018-03-21 12:13:37 -04001077// Check that the texture-specific flags (i.e., for external & rectangle textures) work
1078// for promise images. As such, this is a GL-only test.
1079DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLTextureFlagsTest, reporter, ctxInfo) {
1080 GrContext* context = ctxInfo.grContext();
1081
1082 SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
1083 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
1084
1085 SkSurfaceCharacterization characterization;
1086 SkAssertResult(s->characterize(&characterization));
1087
1088 SkDeferredDisplayListRecorder recorder(characterization);
1089
1090 for (GrGLenum target : { GR_GL_TEXTURE_EXTERNAL, GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_2D } ) {
Greg Daniel09c94002018-06-08 22:11:51 +00001091 for (auto mipMapped : { GrMipMapped::kNo, GrMipMapped::kYes }) {
1092 GrBackendFormat format = GrBackendFormat::MakeGL(GR_GL_RGBA8, target);
Robert Phillipsabf7b762018-03-21 12:13:37 -04001093
Brian Salomonf55e8d52019-01-30 17:28:20 -05001094 sk_sp<SkImage> image = recorder.makePromiseTexture(
1095 format, 32, 32, mipMapped,
1096 kTopLeft_GrSurfaceOrigin,
1097 kRGBA_8888_SkColorType,
1098 kPremul_SkAlphaType, nullptr,
1099 dummy_fulfill_proc,
1100 dummy_release_proc,
1101 dummy_done_proc,
Brian Salomon0cc57542019-03-08 13:28:46 -05001102 nullptr,
1103 SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
Greg Daniel09c94002018-06-08 22:11:51 +00001104 if (GR_GL_TEXTURE_2D != target && mipMapped == GrMipMapped::kYes) {
1105 REPORTER_ASSERT(reporter, !image);
1106 continue;
1107 }
1108 REPORTER_ASSERT(reporter, image);
Robert Phillipsabf7b762018-03-21 12:13:37 -04001109
Jim Van Verth21bd60d2018-10-12 15:00:20 -04001110 GrTextureProxy* backingProxy = ((SkImage_GpuBase*) image.get())->peekProxy();
Robert Phillipsabf7b762018-03-21 12:13:37 -04001111
Greg Daniel09c94002018-06-08 22:11:51 +00001112 REPORTER_ASSERT(reporter, backingProxy->mipMapped() == mipMapped);
1113 if (GR_GL_TEXTURE_2D == target) {
Brian Salomonfd98c2c2018-07-31 17:25:29 -04001114 REPORTER_ASSERT(reporter, !backingProxy->hasRestrictedSampling());
Greg Daniel09c94002018-06-08 22:11:51 +00001115 } else {
Brian Salomonfd98c2c2018-07-31 17:25:29 -04001116 REPORTER_ASSERT(reporter, backingProxy->hasRestrictedSampling());
Greg Daniel09c94002018-06-08 22:11:51 +00001117 }
Robert Phillipsabf7b762018-03-21 12:13:37 -04001118 }
1119 }
Robert Phillipsbe77a022018-04-03 17:17:05 -04001120}
John Rosascoa9b348f2019-11-08 13:18:15 -08001121#endif // SK_GL
Robert Phillipsbe77a022018-04-03 17:17:05 -04001122
1123////////////////////////////////////////////////////////////////////////////////
Robert Phillips646f6372018-09-25 09:31:10 -04001124// Test colorType and pixelConfig compatibility.
Robert Phillipsbe77a022018-04-03 17:17:05 -04001125DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLCompatibilityTest, reporter, ctxInfo) {
1126 GrContext* context = ctxInfo.grContext();
1127
1128 for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
1129 SkColorType colorType = static_cast<SkColorType>(ct);
1130
Robert Phillips3cd54322019-07-10 09:28:59 -04001131 SurfaceParameters params(context);
Greg Daniel60ea40c2019-02-12 13:38:44 -05001132 params.setColorType(colorType);
1133 params.setColorSpace(nullptr);
Robert Phillipsbe77a022018-04-03 17:17:05 -04001134
Brian Salomon4687bdd2019-05-09 16:28:04 -04001135 if (!context->priv().caps()->mipMapSupport()) {
1136 params.setShouldCreateMipMaps(false);
1137 }
Greg Daniel60ea40c2019-02-12 13:38:44 -05001138
Robert Phillipsd8f79a22019-06-24 13:25:42 -04001139 test_make_render_target(reporter, context, params);
Robert Phillipsbe77a022018-04-03 17:17:05 -04001140 }
Robert Phillipsabf7b762018-03-21 12:13:37 -04001141
1142}