DeferredDisplayListTest.cpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  1. /*
  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. #include "include/core/SkBitmap.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkColor.h"
  10. #include "include/core/SkColorSpace.h"
  11. #include "include/core/SkDeferredDisplayListRecorder.h"
  12. #include "include/core/SkImage.h"
  13. #include "include/core/SkImageInfo.h"
  14. #include "include/core/SkPaint.h"
  15. #include "include/core/SkPromiseImageTexture.h"
  16. #include "include/core/SkRect.h"
  17. #include "include/core/SkRefCnt.h"
  18. #include "include/core/SkSurface.h"
  19. #include "include/core/SkSurfaceCharacterization.h"
  20. #include "include/core/SkSurfaceProps.h"
  21. #include "include/core/SkTypes.h"
  22. #include "include/gpu/GrBackendSurface.h"
  23. #include "include/gpu/GrContext.h"
  24. #include "include/gpu/GrContextThreadSafeProxy.h"
  25. #include "include/gpu/GrTypes.h"
  26. #include "include/gpu/gl/GrGLTypes.h"
  27. #include "include/private/GrTypesPriv.h"
  28. #include "include/private/SkDeferredDisplayList.h"
  29. #include "src/core/SkDeferredDisplayListPriv.h"
  30. #include "src/gpu/GrCaps.h"
  31. #include "src/gpu/GrContextPriv.h"
  32. #include "src/gpu/GrGpu.h"
  33. #include "src/gpu/GrRenderTargetContext.h"
  34. #include "src/gpu/GrRenderTargetProxy.h"
  35. #include "src/gpu/GrTextureProxy.h"
  36. #include "src/gpu/SkGpuDevice.h"
  37. #include "src/gpu/gl/GrGLDefines.h"
  38. #include "src/image/SkImage_GpuBase.h"
  39. #include "src/image/SkSurface_Gpu.h"
  40. #include "tests/Test.h"
  41. #include "tests/TestUtils.h"
  42. #include "tools/gpu/GrContextFactory.h"
  43. #include <initializer_list>
  44. #include <memory>
  45. #include <utility>
  46. #ifdef SK_VULKAN
  47. #include "src/gpu/vk/GrVkCaps.h"
  48. #endif
  49. class SurfaceParameters {
  50. public:
  51. static const int kNumParams = 12;
  52. static const int kSampleCount = 5;
  53. static const int kMipMipCount = 8;
  54. static const int kFBO0Count = 9;
  55. static const int kProtectedCount = 11;
  56. SurfaceParameters(GrContext* context)
  57. : fBackend(context->backend())
  58. , fWidth(64)
  59. , fHeight(64)
  60. , fOrigin(kTopLeft_GrSurfaceOrigin)
  61. , fColorType(kRGBA_8888_SkColorType)
  62. , fColorSpace(SkColorSpace::MakeSRGB())
  63. , fSampleCount(1)
  64. , fSurfaceProps(0x0, kUnknown_SkPixelGeometry)
  65. , fShouldCreateMipMaps(true)
  66. , fUsesGLFBO0(false)
  67. , fIsTextureable(true)
  68. , fIsProtected(GrProtected::kNo) {
  69. #ifdef SK_VULKAN
  70. if (GrBackendApi::kVulkan == context->backend()) {
  71. const GrVkCaps* vkCaps = (const GrVkCaps*) context->priv().caps();
  72. fIsProtected = GrProtected(vkCaps->supportsProtectedMemory());
  73. }
  74. #endif
  75. }
  76. int sampleCount() const { return fSampleCount; }
  77. void setColorType(SkColorType ct) { fColorType = ct; }
  78. SkColorType colorType() const { return fColorType; }
  79. void setColorSpace(sk_sp<SkColorSpace> cs) { fColorSpace = std::move(cs); }
  80. void setTextureable(bool isTextureable) { fIsTextureable = isTextureable; }
  81. void setShouldCreateMipMaps(bool shouldCreateMipMaps) {
  82. fShouldCreateMipMaps = shouldCreateMipMaps;
  83. }
  84. // Modify the SurfaceParameters in just one way
  85. void modify(int i) {
  86. switch (i) {
  87. case 0:
  88. fWidth = 63;
  89. break;
  90. case 1:
  91. fHeight = 63;
  92. break;
  93. case 2:
  94. fOrigin = kBottomLeft_GrSurfaceOrigin;
  95. break;
  96. case 3:
  97. fColorType = kRGBA_F16_SkColorType;
  98. break;
  99. case 4:
  100. // This just needs to be a colorSpace different from that returned by MakeSRGB().
  101. // In this case we just change the gamut.
  102. fColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kAdobeRGB);
  103. break;
  104. case kSampleCount:
  105. fSampleCount = 4;
  106. break;
  107. case 6:
  108. fSurfaceProps = SkSurfaceProps(0x0, kRGB_H_SkPixelGeometry);
  109. break;
  110. case 7:
  111. fSurfaceProps = SkSurfaceProps(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
  112. kUnknown_SkPixelGeometry);
  113. break;
  114. case 8:
  115. fShouldCreateMipMaps = false;
  116. break;
  117. case 9:
  118. if (GrBackendApi::kOpenGL == fBackend) {
  119. fUsesGLFBO0 = true;
  120. fShouldCreateMipMaps = false; // needs to changed in tandem w/ textureability
  121. fIsTextureable = false;
  122. }
  123. break;
  124. case 10:
  125. fShouldCreateMipMaps = false; // needs to changed in tandem w/ textureability
  126. fIsTextureable = false;
  127. break;
  128. case 11:
  129. fIsProtected = GrProtected::kYes == fIsProtected ? GrProtected::kNo
  130. : GrProtected::kYes;
  131. break;
  132. }
  133. }
  134. SkSurfaceCharacterization createCharacterization(GrContext* context) const {
  135. int maxResourceCount;
  136. size_t maxResourceBytes;
  137. context->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes);
  138. // Note that Ganesh doesn't make use of the SkImageInfo's alphaType
  139. SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType,
  140. kPremul_SkAlphaType, fColorSpace);
  141. const GrCaps* caps = context->priv().caps();
  142. GrBackendFormat backendFormat =
  143. caps->getBackendFormatFromColorType(SkColorTypeToGrColorType(fColorType));
  144. if (!backendFormat.isValid()) {
  145. return SkSurfaceCharacterization();
  146. }
  147. SkSurfaceCharacterization c = context->threadSafeProxy()->createCharacterization(
  148. maxResourceBytes, ii, backendFormat, fSampleCount,
  149. fOrigin, fSurfaceProps, fShouldCreateMipMaps,
  150. fUsesGLFBO0, fIsTextureable, fIsProtected);
  151. return c;
  152. }
  153. // Create a DDL whose characterization captures the current settings
  154. std::unique_ptr<SkDeferredDisplayList> createDDL(GrContext* context) const {
  155. SkSurfaceCharacterization c = this->createCharacterization(context);
  156. SkAssertResult(c.isValid());
  157. SkDeferredDisplayListRecorder r(c);
  158. SkCanvas* canvas = r.getCanvas();
  159. if (!canvas) {
  160. return nullptr;
  161. }
  162. canvas->drawRect(SkRect::MakeXYWH(10, 10, 10, 10), SkPaint());
  163. return r.detach();
  164. }
  165. // Create the surface with the current set of parameters
  166. sk_sp<SkSurface> make(GrContext* context, GrBackendTexture* backend) const {
  167. const SkSurfaceCharacterization c = this->createCharacterization(context);
  168. GrMipMapped mipmapped = !fIsTextureable
  169. ? GrMipMapped::kNo
  170. : GrMipMapped(fShouldCreateMipMaps);
  171. if (fUsesGLFBO0) {
  172. if (GrBackendApi::kOpenGL != context->backend()) {
  173. return nullptr;
  174. }
  175. GrGLFramebufferInfo fboInfo;
  176. fboInfo.fFBOID = 0;
  177. fboInfo.fFormat = GR_GL_RGBA8;
  178. static constexpr int kStencilBits = 8;
  179. GrBackendRenderTarget backendRT(fWidth, fHeight, 1, kStencilBits, fboInfo);
  180. if (!backendRT.isValid()) {
  181. return nullptr;
  182. }
  183. sk_sp<SkSurface> result = SkSurface::MakeFromBackendRenderTarget(context, backendRT,
  184. fOrigin, fColorType,
  185. fColorSpace,
  186. &fSurfaceProps);
  187. SkASSERT(result->isCompatible(c));
  188. return result;
  189. }
  190. *backend = context->createBackendTexture(fWidth, fHeight, fColorType,
  191. SkColors::kTransparent,
  192. mipmapped, GrRenderable::kYes, fIsProtected);
  193. if (!backend->isValid()) {
  194. return nullptr;
  195. }
  196. // Even if a characterization couldn't be constructed we want to soldier on to make
  197. // sure that surface creation will/would've also failed
  198. SkASSERT(!c.isValid() || c.isCompatible(*backend));
  199. sk_sp<SkSurface> surface;
  200. if (!fIsTextureable) {
  201. // Create a surface w/ the current parameters but make it non-textureable
  202. surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
  203. context, *backend, fOrigin, fSampleCount, fColorType,
  204. fColorSpace, &fSurfaceProps);
  205. } else {
  206. surface = SkSurface::MakeFromBackendTexture(
  207. context, *backend, fOrigin, fSampleCount, fColorType,
  208. fColorSpace, &fSurfaceProps);
  209. }
  210. if (!surface) {
  211. SkASSERT(!c.isValid());
  212. this->cleanUpBackEnd(context, *backend);
  213. return nullptr;
  214. }
  215. SkASSERT(c.isValid());
  216. SkASSERT(surface->isCompatible(c));
  217. return surface;
  218. }
  219. void cleanUpBackEnd(GrContext* context, const GrBackendTexture& backend) const {
  220. context->deleteBackendTexture(backend);
  221. }
  222. private:
  223. GrBackendApi fBackend;
  224. int fWidth;
  225. int fHeight;
  226. GrSurfaceOrigin fOrigin;
  227. SkColorType fColorType;
  228. sk_sp<SkColorSpace> fColorSpace;
  229. int fSampleCount;
  230. SkSurfaceProps fSurfaceProps;
  231. bool fShouldCreateMipMaps;
  232. bool fUsesGLFBO0;
  233. bool fIsTextureable;
  234. GrProtected fIsProtected;
  235. };
  236. // Test out operator== && operator!=
  237. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLOperatorEqTest, reporter, ctxInfo) {
  238. GrContext* context = ctxInfo.grContext();
  239. for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
  240. SurfaceParameters params1(context);
  241. params1.modify(i);
  242. SkSurfaceCharacterization char1 = params1.createCharacterization(context);
  243. if (!char1.isValid()) {
  244. continue; // can happen on some platforms (ChromeOS)
  245. }
  246. for (int j = 0; j < SurfaceParameters::kNumParams; ++j) {
  247. SurfaceParameters params2(context);
  248. params2.modify(j);
  249. SkSurfaceCharacterization char2 = params2.createCharacterization(context);
  250. if (!char2.isValid()) {
  251. continue; // can happen on some platforms (ChromeOS)
  252. }
  253. if (i == j) {
  254. REPORTER_ASSERT(reporter, char1 == char2);
  255. } else {
  256. REPORTER_ASSERT(reporter, char1 != char2);
  257. }
  258. }
  259. }
  260. {
  261. SurfaceParameters params(context);
  262. SkSurfaceCharacterization valid = params.createCharacterization(context);
  263. SkASSERT(valid.isValid());
  264. SkSurfaceCharacterization inval1, inval2;
  265. SkASSERT(!inval1.isValid() && !inval2.isValid());
  266. REPORTER_ASSERT(reporter, inval1 != inval2);
  267. REPORTER_ASSERT(reporter, valid != inval1);
  268. REPORTER_ASSERT(reporter, inval1 != valid);
  269. }
  270. }
  271. ////////////////////////////////////////////////////////////////////////////////
  272. // This tests SkSurfaceCharacterization/SkSurface compatibility
  273. void DDLSurfaceCharacterizationTestImpl(GrContext* context, skiatest::Reporter* reporter) {
  274. GrGpu* gpu = context->priv().getGpu();
  275. const GrCaps* caps = context->priv().caps();
  276. // Create a bitmap that we can readback into
  277. SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
  278. kPremul_SkAlphaType);
  279. SkBitmap bitmap;
  280. bitmap.allocPixels(imageInfo);
  281. std::unique_ptr<SkDeferredDisplayList> ddl;
  282. // First, create a DDL using the stock SkSurface parameters
  283. {
  284. SurfaceParameters params(context);
  285. ddl = params.createDDL(context);
  286. SkAssertResult(ddl);
  287. // The DDL should draw into an SkSurface created with the same parameters
  288. GrBackendTexture backend;
  289. sk_sp<SkSurface> s = params.make(context, &backend);
  290. if (!s) {
  291. return;
  292. }
  293. REPORTER_ASSERT(reporter, s->draw(ddl.get()));
  294. s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
  295. context->flush();
  296. gpu->testingOnly_flushGpuAndSync();
  297. s = nullptr;
  298. params.cleanUpBackEnd(context, backend);
  299. }
  300. // Then, alter each parameter in turn and check that the DDL & surface are incompatible
  301. for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
  302. SurfaceParameters params(context);
  303. params.modify(i);
  304. if (SurfaceParameters::kProtectedCount == i) {
  305. if (context->backend() != GrBackendApi::kVulkan) {
  306. // Only the Vulkan backend respects the protected parameter
  307. continue;
  308. }
  309. #ifdef SK_VULKAN
  310. const GrVkCaps* vkCaps = (const GrVkCaps*) context->priv().caps();
  311. // And, even then, only when it is a protected context
  312. if (!vkCaps->supportsProtectedMemory()) {
  313. continue;
  314. }
  315. #endif
  316. }
  317. GrBackendTexture backend;
  318. sk_sp<SkSurface> s = params.make(context, &backend);
  319. if (!s) {
  320. continue;
  321. }
  322. if (SurfaceParameters::kSampleCount == i) {
  323. int supportedSampleCount = caps->getRenderTargetSampleCount(
  324. params.sampleCount(), SkColorTypeToGrColorType(params.colorType()),
  325. backend.getBackendFormat());
  326. if (1 == supportedSampleCount) {
  327. // If changing the sample count won't result in a different
  328. // surface characterization, skip this step
  329. s = nullptr;
  330. params.cleanUpBackEnd(context, backend);
  331. continue;
  332. }
  333. }
  334. if (SurfaceParameters::kMipMipCount == i && !caps->mipMapSupport()) {
  335. // If changing the mipmap setting won't result in a different surface characterization,
  336. // skip this step
  337. s = nullptr;
  338. params.cleanUpBackEnd(context, backend);
  339. continue;
  340. }
  341. if (SurfaceParameters::kFBO0Count == i && context->backend() != GrBackendApi::kOpenGL) {
  342. // FBO0 only affects the surface characterization when using OpenGL
  343. s = nullptr;
  344. params.cleanUpBackEnd(context, backend);
  345. continue;
  346. }
  347. REPORTER_ASSERT(reporter, !s->draw(ddl.get()),
  348. "DDLSurfaceCharacterizationTest failed on parameter: %d\n", i);
  349. context->flush();
  350. gpu->testingOnly_flushGpuAndSync();
  351. s = nullptr;
  352. params.cleanUpBackEnd(context, backend);
  353. }
  354. // Next test the compatibility of resource cache parameters
  355. {
  356. const SurfaceParameters params(context);
  357. GrBackendTexture backend;
  358. sk_sp<SkSurface> s = params.make(context, &backend);
  359. int maxResourceCount;
  360. size_t maxResourceBytes;
  361. context->getResourceCacheLimits(&maxResourceCount, &maxResourceBytes);
  362. context->setResourceCacheLimits(maxResourceCount, maxResourceBytes/2);
  363. REPORTER_ASSERT(reporter, !s->draw(ddl.get()));
  364. // DDL TODO: once proxies/ops can be de-instantiated we can re-enable these tests.
  365. // For now, DDLs are drawn once.
  366. #if 0
  367. // resource limits >= those at characterization time are accepted
  368. context->setResourceCacheLimits(2*maxResourceCount, maxResourceBytes);
  369. REPORTER_ASSERT(reporter, s->draw(ddl.get()));
  370. s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
  371. context->setResourceCacheLimits(maxResourceCount, 2*maxResourceBytes);
  372. REPORTER_ASSERT(reporter, s->draw(ddl.get()));
  373. s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
  374. context->setResourceCacheLimits(maxResourceCount, maxResourceBytes);
  375. REPORTER_ASSERT(reporter, s->draw(ddl.get()));
  376. s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
  377. #endif
  378. context->flush();
  379. gpu->testingOnly_flushGpuAndSync();
  380. s = nullptr;
  381. params.cleanUpBackEnd(context, backend);
  382. }
  383. // Test that the textureability of the DDL characterization can block a DDL draw
  384. {
  385. GrBackendTexture backend;
  386. SurfaceParameters params(context);
  387. params.setShouldCreateMipMaps(false);
  388. params.setTextureable(false);
  389. sk_sp<SkSurface> s = params.make(context, &backend);
  390. if (s) {
  391. REPORTER_ASSERT(reporter, !s->draw(ddl.get())); // bc the DDL was made w/ textureability
  392. context->flush();
  393. gpu->testingOnly_flushGpuAndSync();
  394. s = nullptr;
  395. params.cleanUpBackEnd(context, backend);
  396. }
  397. }
  398. // Make sure non-GPU-backed surfaces fail characterization
  399. {
  400. SkImageInfo ii = SkImageInfo::MakeN32(64, 64, kOpaque_SkAlphaType);
  401. sk_sp<SkSurface> rasterSurface = SkSurface::MakeRaster(ii);
  402. SkSurfaceCharacterization c;
  403. REPORTER_ASSERT(reporter, !rasterSurface->characterize(&c));
  404. }
  405. // Exercise the createResized method
  406. {
  407. SurfaceParameters params(context);
  408. GrBackendTexture backend;
  409. sk_sp<SkSurface> s = params.make(context, &backend);
  410. if (!s) {
  411. return;
  412. }
  413. SkSurfaceCharacterization char0;
  414. SkAssertResult(s->characterize(&char0));
  415. // Too small
  416. SkSurfaceCharacterization char1 = char0.createResized(-1, -1);
  417. REPORTER_ASSERT(reporter, !char1.isValid());
  418. // Too large
  419. SkSurfaceCharacterization char2 = char0.createResized(1000000, 32);
  420. REPORTER_ASSERT(reporter, !char2.isValid());
  421. // Just right
  422. SkSurfaceCharacterization char3 = char0.createResized(32, 32);
  423. REPORTER_ASSERT(reporter, char3.isValid());
  424. REPORTER_ASSERT(reporter, 32 == char3.width());
  425. REPORTER_ASSERT(reporter, 32 == char3.height());
  426. s = nullptr;
  427. params.cleanUpBackEnd(context, backend);
  428. }
  429. }
  430. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSurfaceCharacterizationTest, reporter, ctxInfo) {
  431. GrContext* context = ctxInfo.grContext();
  432. DDLSurfaceCharacterizationTestImpl(context, reporter);
  433. }
  434. // Test that a DDL created w/o textureability can be replayed into both a textureable and
  435. // non-textureable destination. Note that DDLSurfaceCharacterizationTest tests that a
  436. // textureable DDL cannot be played into a non-textureable destination but can be replayed
  437. // into a textureable destination.
  438. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLNonTextureabilityTest, reporter, ctxInfo) {
  439. GrContext* context = ctxInfo.grContext();
  440. GrGpu* gpu = context->priv().getGpu();
  441. // Create a bitmap that we can readback into
  442. SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
  443. kPremul_SkAlphaType);
  444. SkBitmap bitmap;
  445. bitmap.allocPixels(imageInfo);
  446. for (bool textureability : { true, false }) {
  447. std::unique_ptr<SkDeferredDisplayList> ddl;
  448. // First, create a DDL w/o textureability (and thus no mipmaps). TODO: once we have
  449. // reusable DDLs, move this outside of the loop.
  450. {
  451. SurfaceParameters params(context);
  452. params.setShouldCreateMipMaps(false);
  453. params.setTextureable(false);
  454. ddl = params.createDDL(context);
  455. SkAssertResult(ddl);
  456. }
  457. // Then verify it can draw into either flavor of destination
  458. SurfaceParameters params(context);
  459. params.setShouldCreateMipMaps(textureability);
  460. params.setTextureable(textureability);
  461. GrBackendTexture backend;
  462. sk_sp<SkSurface> s = params.make(context, &backend);
  463. if (!s) {
  464. continue;
  465. }
  466. REPORTER_ASSERT(reporter, s->draw(ddl.get()));
  467. s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
  468. context->flush();
  469. gpu->testingOnly_flushGpuAndSync();
  470. s = nullptr;
  471. params.cleanUpBackEnd(context, backend);
  472. }
  473. }
  474. static void test_make_render_target(skiatest::Reporter* reporter,
  475. GrContext* context,
  476. const SurfaceParameters& params) {
  477. {
  478. const SkSurfaceCharacterization c = params.createCharacterization(context);
  479. if (!c.isValid()) {
  480. GrBackendTexture backend;
  481. sk_sp<SkSurface> tmp = params.make(context, &backend);
  482. // If we couldn't characterize the surface we shouldn't be able to create it either
  483. REPORTER_ASSERT(reporter, !tmp);
  484. if (tmp) {
  485. tmp = nullptr;
  486. params.cleanUpBackEnd(context, backend);
  487. }
  488. return;
  489. }
  490. }
  491. const SkSurfaceCharacterization c = params.createCharacterization(context);
  492. GrBackendTexture backend;
  493. {
  494. sk_sp<SkSurface> s = params.make(context, &backend);
  495. REPORTER_ASSERT(reporter, s);
  496. if (!s) {
  497. REPORTER_ASSERT(reporter, !c.isValid());
  498. params.cleanUpBackEnd(context, backend);
  499. return;
  500. }
  501. REPORTER_ASSERT(reporter, c.isValid());
  502. REPORTER_ASSERT(reporter, c.isCompatible(backend));
  503. REPORTER_ASSERT(reporter, s->isCompatible(c));
  504. // Note that we're leaving 'backend' live here
  505. }
  506. // Make an SkSurface from scratch
  507. {
  508. sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, c, SkBudgeted::kYes);
  509. REPORTER_ASSERT(reporter, s);
  510. REPORTER_ASSERT(reporter, s->isCompatible(c));
  511. }
  512. // Make an SkSurface that wraps the existing backend texture
  513. {
  514. sk_sp<SkSurface> s = SkSurface::MakeFromBackendTexture(context, c, backend);
  515. REPORTER_ASSERT(reporter, s);
  516. REPORTER_ASSERT(reporter, s->isCompatible(c));
  517. }
  518. params.cleanUpBackEnd(context, backend);
  519. }
  520. ////////////////////////////////////////////////////////////////////////////////
  521. // This tests the SkSurface::MakeRenderTarget variants that take an SkSurfaceCharacterization.
  522. // In particular, the SkSurface, backendTexture and SkSurfaceCharacterization
  523. // should always be compatible.
  524. void DDLMakeRenderTargetTestImpl(GrContext* context, skiatest::Reporter* reporter) {
  525. for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
  526. if (SurfaceParameters::kFBO0Count == i) {
  527. // MakeRenderTarget doesn't support FBO0
  528. continue;
  529. }
  530. if (SurfaceParameters::kProtectedCount == i) {
  531. if (context->backend() != GrBackendApi::kVulkan) {
  532. // Only the Vulkan backend respects the protected parameter
  533. continue;
  534. }
  535. #ifdef SK_VULKAN
  536. const GrVkCaps* vkCaps = (const GrVkCaps*) context->priv().caps();
  537. // And, even then, only when it is a protected context
  538. if (!vkCaps->supportsProtectedMemory()) {
  539. continue;
  540. }
  541. #endif
  542. }
  543. SurfaceParameters params(context);
  544. params.modify(i);
  545. if (!context->priv().caps()->mipMapSupport()) {
  546. params.setShouldCreateMipMaps(false);
  547. }
  548. test_make_render_target(reporter, context, params);
  549. }
  550. }
  551. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMakeRenderTargetTest, reporter, ctxInfo) {
  552. GrContext* context = ctxInfo.grContext();
  553. DDLMakeRenderTargetTestImpl(context, reporter);
  554. }
  555. ////////////////////////////////////////////////////////////////////////////////
  556. static constexpr int kSize = 8;
  557. struct TextureReleaseChecker {
  558. TextureReleaseChecker() : fReleaseCount(0) {}
  559. int fReleaseCount;
  560. static void Release(void* self) {
  561. static_cast<TextureReleaseChecker*>(self)->fReleaseCount++;
  562. }
  563. };
  564. enum class DDLStage { kMakeImage, kDrawImage, kDetach, kDrawDDL };
  565. // This tests the ability to create and use wrapped textures in a DDL world
  566. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest, reporter, ctxInfo) {
  567. GrContext* context = ctxInfo.grContext();
  568. GrBackendTexture backendTex = context->createBackendTexture(
  569. kSize, kSize, kRGBA_8888_SkColorType,
  570. SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
  571. if (!backendTex.isValid()) {
  572. return;
  573. }
  574. SurfaceParameters params(context);
  575. GrBackendTexture backend;
  576. sk_sp<SkSurface> s = params.make(context, &backend);
  577. if (!s) {
  578. context->deleteBackendTexture(backendTex);
  579. return;
  580. }
  581. SkSurfaceCharacterization c;
  582. SkAssertResult(s->characterize(&c));
  583. std::unique_ptr<SkDeferredDisplayListRecorder> recorder(new SkDeferredDisplayListRecorder(c));
  584. SkCanvas* canvas = recorder->getCanvas();
  585. if (!canvas) {
  586. s = nullptr;
  587. params.cleanUpBackEnd(context, backend);
  588. context->deleteBackendTexture(backendTex);
  589. return;
  590. }
  591. GrContext* deferredContext = canvas->getGrContext();
  592. if (!deferredContext) {
  593. s = nullptr;
  594. params.cleanUpBackEnd(context, backend);
  595. context->deleteBackendTexture(backendTex);
  596. return;
  597. }
  598. // Wrapped Backend Textures are not supported in DDL
  599. sk_sp<SkImage> image =
  600. SkImage::MakeFromAdoptedTexture(deferredContext, backendTex, kTopLeft_GrSurfaceOrigin,
  601. kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
  602. REPORTER_ASSERT(reporter, !image);
  603. TextureReleaseChecker releaseChecker;
  604. image = SkImage::MakeFromTexture(deferredContext, backendTex, kTopLeft_GrSurfaceOrigin,
  605. kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr,
  606. TextureReleaseChecker::Release, &releaseChecker);
  607. REPORTER_ASSERT(reporter, !image);
  608. context->deleteBackendTexture(backendTex);
  609. s = nullptr;
  610. params.cleanUpBackEnd(context, backend);
  611. }
  612. static sk_sp<SkPromiseImageTexture> dummy_fulfill_proc(void*) {
  613. SkASSERT(0);
  614. return nullptr;
  615. }
  616. static void dummy_release_proc(void*) { SkASSERT(0); }
  617. static void dummy_done_proc(void*) {}
  618. ////////////////////////////////////////////////////////////////////////////////
  619. // Test out the behavior of an invalid DDLRecorder
  620. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLInvalidRecorder, reporter, ctxInfo) {
  621. GrContext* context = ctxInfo.grContext();
  622. {
  623. SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
  624. sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
  625. SkSurfaceCharacterization characterization;
  626. SkAssertResult(s->characterize(&characterization));
  627. // never calling getCanvas means the backing surface is never allocated
  628. SkDeferredDisplayListRecorder recorder(characterization);
  629. }
  630. {
  631. SkSurfaceCharacterization invalid;
  632. SkDeferredDisplayListRecorder recorder(invalid);
  633. const SkSurfaceCharacterization c = recorder.characterization();
  634. REPORTER_ASSERT(reporter, !c.isValid());
  635. REPORTER_ASSERT(reporter, !recorder.getCanvas());
  636. REPORTER_ASSERT(reporter, !recorder.detach());
  637. const GrCaps* caps = context->priv().caps();
  638. GrBackendFormat format = caps->getBackendFormatFromColorType(GrColorType::kRGBA_8888);
  639. sk_sp<SkImage> image = recorder.makePromiseTexture(
  640. format, 32, 32, GrMipMapped::kNo,
  641. kTopLeft_GrSurfaceOrigin,
  642. kRGBA_8888_SkColorType,
  643. kPremul_SkAlphaType, nullptr,
  644. dummy_fulfill_proc,
  645. dummy_release_proc,
  646. dummy_done_proc,
  647. nullptr,
  648. SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
  649. REPORTER_ASSERT(reporter, !image);
  650. }
  651. }
  652. ////////////////////////////////////////////////////////////////////////////////
  653. // Ensure that flushing while DDL recording doesn't cause a crash
  654. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLFlushWhileRecording, reporter, ctxInfo) {
  655. GrContext* context = ctxInfo.grContext();
  656. SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
  657. sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
  658. SkSurfaceCharacterization characterization;
  659. SkAssertResult(s->characterize(&characterization));
  660. SkDeferredDisplayListRecorder recorder(characterization);
  661. SkCanvas* canvas = recorder.getCanvas();
  662. canvas->getGrContext()->flush();
  663. }
  664. ////////////////////////////////////////////////////////////////////////////////
  665. // Test that flushing a DDL via SkSurface::flush works
  666. struct FulfillInfo {
  667. sk_sp<SkPromiseImageTexture> fTex;
  668. bool fFulfilled = false;
  669. bool fReleased = false;
  670. bool fDone = false;
  671. };
  672. static sk_sp<SkPromiseImageTexture> tracking_fulfill_proc(void* context) {
  673. FulfillInfo* info = (FulfillInfo*) context;
  674. info->fFulfilled = true;
  675. return info->fTex;
  676. }
  677. static void tracking_release_proc(void* context) {
  678. FulfillInfo* info = (FulfillInfo*) context;
  679. info->fReleased = true;
  680. }
  681. static void tracking_done_proc(void* context) {
  682. FulfillInfo* info = (FulfillInfo*) context;
  683. info->fDone = true;
  684. }
  685. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLSkSurfaceFlush, reporter, ctxInfo) {
  686. GrContext* context = ctxInfo.grContext();
  687. SkImageInfo ii = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
  688. sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
  689. SkSurfaceCharacterization characterization;
  690. SkAssertResult(s->characterize(&characterization));
  691. GrBackendTexture backendTexture;
  692. if (!create_backend_texture(context, &backendTexture, ii, SkColors::kCyan,
  693. GrMipMapped::kNo, GrRenderable::kNo)) {
  694. REPORTER_ASSERT(reporter, false);
  695. return;
  696. }
  697. FulfillInfo fulfillInfo;
  698. fulfillInfo.fTex = SkPromiseImageTexture::Make(backendTexture);
  699. std::unique_ptr<SkDeferredDisplayList> ddl;
  700. {
  701. SkDeferredDisplayListRecorder recorder(characterization);
  702. const GrCaps* caps = context->priv().caps();
  703. GrBackendFormat format = caps->getBackendFormatFromColorType(GrColorType::kRGBA_8888);
  704. sk_sp<SkImage> promiseImage = recorder.makePromiseTexture(
  705. format, 32, 32, GrMipMapped::kNo,
  706. kTopLeft_GrSurfaceOrigin,
  707. kRGBA_8888_SkColorType,
  708. kPremul_SkAlphaType, nullptr,
  709. tracking_fulfill_proc,
  710. tracking_release_proc,
  711. tracking_done_proc,
  712. &fulfillInfo,
  713. SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
  714. SkCanvas* canvas = recorder.getCanvas();
  715. canvas->clear(SK_ColorRED);
  716. canvas->drawImage(promiseImage, 0, 0);
  717. ddl = recorder.detach();
  718. }
  719. context->flush();
  720. s->draw(ddl.get());
  721. GrFlushInfo flushInfo;
  722. s->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
  723. REPORTER_ASSERT(reporter, fulfillInfo.fFulfilled);
  724. REPORTER_ASSERT(reporter, fulfillInfo.fReleased);
  725. if (GrBackendApi::kVulkan == context->backend() ||
  726. GrBackendApi::kMetal == context->backend()) {
  727. // In order to receive the done callback with Vulkan we need to perform the equivalent
  728. // of a glFinish
  729. GrFlushInfo flushInfoSyncCpu;
  730. flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
  731. s->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfoSyncCpu);
  732. }
  733. REPORTER_ASSERT(reporter, fulfillInfo.fDone);
  734. REPORTER_ASSERT(reporter, fulfillInfo.fTex->unique());
  735. fulfillInfo.fTex.reset();
  736. delete_backend_texture(context, backendTexture);
  737. }
  738. ////////////////////////////////////////////////////////////////////////////////
  739. // Ensure that reusing a single DDLRecorder to create multiple DDLs works cleanly
  740. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DDLMultipleDDLs, reporter, ctxInfo) {
  741. GrContext* context = ctxInfo.grContext();
  742. SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
  743. sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
  744. SkBitmap bitmap;
  745. bitmap.allocPixels(ii);
  746. SkSurfaceCharacterization characterization;
  747. SkAssertResult(s->characterize(&characterization));
  748. SkDeferredDisplayListRecorder recorder(characterization);
  749. SkCanvas* canvas1 = recorder.getCanvas();
  750. canvas1->clear(SK_ColorRED);
  751. canvas1->save();
  752. canvas1->clipRect(SkRect::MakeXYWH(8, 8, 16, 16));
  753. std::unique_ptr<SkDeferredDisplayList> ddl1 = recorder.detach();
  754. SkCanvas* canvas2 = recorder.getCanvas();
  755. SkPaint p;
  756. p.setColor(SK_ColorGREEN);
  757. canvas2->drawRect(SkRect::MakeWH(32, 32), p);
  758. std::unique_ptr<SkDeferredDisplayList> ddl2 = recorder.detach();
  759. REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData());
  760. REPORTER_ASSERT(reporter, ddl2->priv().lazyProxyData());
  761. // The lazy proxy data being different ensures that the SkSurface, SkCanvas and backing-
  762. // lazy proxy are all different between the two DDLs
  763. REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData() != ddl2->priv().lazyProxyData());
  764. s->draw(ddl1.get());
  765. s->draw(ddl2.get());
  766. // Make sure the clipRect from DDL1 didn't percolate into DDL2
  767. s->readPixels(ii, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
  768. for (int y = 0; y < 32; ++y) {
  769. for (int x = 0; x < 32; ++x) {
  770. REPORTER_ASSERT(reporter, bitmap.getColor(x, y) == SK_ColorGREEN);
  771. if (bitmap.getColor(x, y) != SK_ColorGREEN) {
  772. return; // we only really need to report the error once
  773. }
  774. }
  775. }
  776. }
  777. ////////////////////////////////////////////////////////////////////////////////
  778. // Check that the texture-specific flags (i.e., for external & rectangle textures) work
  779. // for promise images. As such, this is a GL-only test.
  780. DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLTextureFlagsTest, reporter, ctxInfo) {
  781. GrContext* context = ctxInfo.grContext();
  782. SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
  783. sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii);
  784. SkSurfaceCharacterization characterization;
  785. SkAssertResult(s->characterize(&characterization));
  786. SkDeferredDisplayListRecorder recorder(characterization);
  787. for (GrGLenum target : { GR_GL_TEXTURE_EXTERNAL, GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_2D } ) {
  788. for (auto mipMapped : { GrMipMapped::kNo, GrMipMapped::kYes }) {
  789. GrBackendFormat format = GrBackendFormat::MakeGL(GR_GL_RGBA8, target);
  790. sk_sp<SkImage> image = recorder.makePromiseTexture(
  791. format, 32, 32, mipMapped,
  792. kTopLeft_GrSurfaceOrigin,
  793. kRGBA_8888_SkColorType,
  794. kPremul_SkAlphaType, nullptr,
  795. dummy_fulfill_proc,
  796. dummy_release_proc,
  797. dummy_done_proc,
  798. nullptr,
  799. SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
  800. if (GR_GL_TEXTURE_2D != target && mipMapped == GrMipMapped::kYes) {
  801. REPORTER_ASSERT(reporter, !image);
  802. continue;
  803. }
  804. REPORTER_ASSERT(reporter, image);
  805. GrTextureProxy* backingProxy = ((SkImage_GpuBase*) image.get())->peekProxy();
  806. REPORTER_ASSERT(reporter, backingProxy->mipMapped() == mipMapped);
  807. if (GR_GL_TEXTURE_2D == target) {
  808. REPORTER_ASSERT(reporter, !backingProxy->hasRestrictedSampling());
  809. } else {
  810. REPORTER_ASSERT(reporter, backingProxy->hasRestrictedSampling());
  811. }
  812. }
  813. }
  814. }
  815. ////////////////////////////////////////////////////////////////////////////////
  816. // Test colorType and pixelConfig compatibility.
  817. DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(DDLCompatibilityTest, reporter, ctxInfo) {
  818. GrContext* context = ctxInfo.grContext();
  819. for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
  820. SkColorType colorType = static_cast<SkColorType>(ct);
  821. SurfaceParameters params(context);
  822. params.setColorType(colorType);
  823. params.setColorSpace(nullptr);
  824. if (!context->priv().caps()->mipMapSupport()) {
  825. params.setShouldCreateMipMaps(false);
  826. }
  827. test_make_render_target(reporter, context, params);
  828. }
  829. }