1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "tests/Test.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkColorFilter.h" 11cb93a386Sopenharmony_ci#include "include/core/SkPromiseImageTexture.h" 12cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSurface.h" 13cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h" 17cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h" 18cb93a386Sopenharmony_ci#include "src/image/SkImage_Gpu.h" 19cb93a386Sopenharmony_ci#include "tools/gpu/ManagedBackendTexture.h" 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ciusing namespace sk_gpu_test; 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_cistruct PromiseTextureChecker { 24cb93a386Sopenharmony_ci // shared indicates whether the backend texture is used to fulfill more than one promise 25cb93a386Sopenharmony_ci // image. 26cb93a386Sopenharmony_ci explicit PromiseTextureChecker(const GrBackendTexture& tex, 27cb93a386Sopenharmony_ci skiatest::Reporter* reporter, 28cb93a386Sopenharmony_ci bool shared) 29cb93a386Sopenharmony_ci : fTexture(SkPromiseImageTexture::Make(tex)), fReporter(reporter), fShared(shared) {} 30cb93a386Sopenharmony_ci sk_sp<SkPromiseImageTexture> fTexture; 31cb93a386Sopenharmony_ci skiatest::Reporter* fReporter; 32cb93a386Sopenharmony_ci bool fShared; 33cb93a386Sopenharmony_ci int fFulfillCount = 0; 34cb93a386Sopenharmony_ci int fReleaseCount = 0; 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ci /** 37cb93a386Sopenharmony_ci * Releases the SkPromiseImageTexture. Used to test that cached GrTexture representations 38cb93a386Sopenharmony_ci * in the cache are freed. 39cb93a386Sopenharmony_ci */ 40cb93a386Sopenharmony_ci void releaseTexture() { fTexture.reset(); } 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci SkTArray<GrUniqueKey> uniqueKeys() const { 43cb93a386Sopenharmony_ci return fTexture->testingOnly_uniqueKeysToInvalidate(); 44cb93a386Sopenharmony_ci } 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ci static sk_sp<SkPromiseImageTexture> Fulfill(void* self) { 47cb93a386Sopenharmony_ci auto checker = static_cast<PromiseTextureChecker*>(self); 48cb93a386Sopenharmony_ci checker->fFulfillCount++; 49cb93a386Sopenharmony_ci return checker->fTexture; 50cb93a386Sopenharmony_ci } 51cb93a386Sopenharmony_ci static void Release(void* self) { static_cast<PromiseTextureChecker*>(self)->fReleaseCount++; } 52cb93a386Sopenharmony_ci}; 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_cienum class ReleaseBalanceExpectation { 55cb93a386Sopenharmony_ci kBalanced, 56cb93a386Sopenharmony_ci kAllUnbalanced, 57cb93a386Sopenharmony_ci kUnknown, 58cb93a386Sopenharmony_ci kUnbalancedByOne, 59cb93a386Sopenharmony_ci kBalancedOrOffByOne, 60cb93a386Sopenharmony_ci}; 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_cistatic void check_fulfill_and_release_cnts(skiatest::Reporter* reporter, 63cb93a386Sopenharmony_ci const PromiseTextureChecker& promiseChecker, 64cb93a386Sopenharmony_ci int expectedFulfillCnt, 65cb93a386Sopenharmony_ci ReleaseBalanceExpectation releaseBalanceExpecation) { 66cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, promiseChecker.fFulfillCount == expectedFulfillCnt); 67cb93a386Sopenharmony_ci if (!expectedFulfillCnt) { 68cb93a386Sopenharmony_ci // Release and Done should only ever be called after Fulfill. 69cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !promiseChecker.fReleaseCount); 70cb93a386Sopenharmony_ci return; 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci int releaseDiff = promiseChecker.fFulfillCount - promiseChecker.fReleaseCount; 73cb93a386Sopenharmony_ci switch (releaseBalanceExpecation) { 74cb93a386Sopenharmony_ci case ReleaseBalanceExpectation::kBalanced: 75cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !releaseDiff); 76cb93a386Sopenharmony_ci break; 77cb93a386Sopenharmony_ci case ReleaseBalanceExpectation::kAllUnbalanced: 78cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, releaseDiff == promiseChecker.fFulfillCount); 79cb93a386Sopenharmony_ci break; 80cb93a386Sopenharmony_ci case ReleaseBalanceExpectation::kUnknown: 81cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 82cb93a386Sopenharmony_ci releaseDiff >= 0 && releaseDiff <= promiseChecker.fFulfillCount); 83cb93a386Sopenharmony_ci break; 84cb93a386Sopenharmony_ci case ReleaseBalanceExpectation::kUnbalancedByOne: 85cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, releaseDiff == 1); 86cb93a386Sopenharmony_ci break; 87cb93a386Sopenharmony_ci case ReleaseBalanceExpectation::kBalancedOrOffByOne: 88cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, releaseDiff == 0 || releaseDiff == 1); 89cb93a386Sopenharmony_ci break; 90cb93a386Sopenharmony_ci } 91cb93a386Sopenharmony_ci} 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_cistatic void check_unfulfilled(const PromiseTextureChecker& promiseChecker, 94cb93a386Sopenharmony_ci skiatest::Reporter* reporter) { 95cb93a386Sopenharmony_ci check_fulfill_and_release_cnts(reporter, promiseChecker, 0, 96cb93a386Sopenharmony_ci ReleaseBalanceExpectation::kBalanced); 97cb93a386Sopenharmony_ci} 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_cistatic void check_only_fulfilled(skiatest::Reporter* reporter, 100cb93a386Sopenharmony_ci const PromiseTextureChecker& promiseChecker, 101cb93a386Sopenharmony_ci int expectedFulfillCnt = 1) { 102cb93a386Sopenharmony_ci check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt, 103cb93a386Sopenharmony_ci ReleaseBalanceExpectation::kAllUnbalanced); 104cb93a386Sopenharmony_ci} 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_cistatic void check_all_flushed_but_not_synced(skiatest::Reporter* reporter, 107cb93a386Sopenharmony_ci const PromiseTextureChecker& promiseChecker, 108cb93a386Sopenharmony_ci GrBackendApi api, 109cb93a386Sopenharmony_ci int expectedFulfillCnt = 1) { 110cb93a386Sopenharmony_ci ReleaseBalanceExpectation releaseBalanceExpectation = ReleaseBalanceExpectation::kBalanced; 111cb93a386Sopenharmony_ci // On Vulkan and D3D Done isn't guaranteed to be called until a sync has occurred. 112cb93a386Sopenharmony_ci if (api == GrBackendApi::kVulkan || api == GrBackendApi::kDirect3D) { 113cb93a386Sopenharmony_ci releaseBalanceExpectation = expectedFulfillCnt == 1 114cb93a386Sopenharmony_ci ? ReleaseBalanceExpectation::kBalancedOrOffByOne 115cb93a386Sopenharmony_ci : ReleaseBalanceExpectation::kUnknown; 116cb93a386Sopenharmony_ci } 117cb93a386Sopenharmony_ci check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt, 118cb93a386Sopenharmony_ci releaseBalanceExpectation); 119cb93a386Sopenharmony_ci} 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_cistatic void check_all_done(skiatest::Reporter* reporter, 122cb93a386Sopenharmony_ci const PromiseTextureChecker& promiseChecker, 123cb93a386Sopenharmony_ci int expectedFulfillCnt = 1) { 124cb93a386Sopenharmony_ci check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt, 125cb93a386Sopenharmony_ci ReleaseBalanceExpectation::kBalanced); 126cb93a386Sopenharmony_ci} 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTest, reporter, ctxInfo) { 129cb93a386Sopenharmony_ci const int kWidth = 10; 130cb93a386Sopenharmony_ci const int kHeight = 10; 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_ci auto ctx = ctxInfo.directContext(); 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ci GrBackendTexture backendTex = ctx->createBackendTexture( 135cb93a386Sopenharmony_ci kWidth, kHeight, kRGBA_8888_SkColorType, 136cb93a386Sopenharmony_ci SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kYes, GrProtected::kNo); 137cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, backendTex.isValid()); 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ci GrBackendFormat backendFormat = backendTex.getBackendFormat(); 140cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, backendFormat.isValid()); 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ci PromiseTextureChecker promiseChecker(backendTex, reporter, false); 143cb93a386Sopenharmony_ci GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin; 144cb93a386Sopenharmony_ci sk_sp<SkImage> refImg(SkImage_Gpu::MakePromiseTexture(ctx->threadSafeProxy(), 145cb93a386Sopenharmony_ci backendFormat, 146cb93a386Sopenharmony_ci {kWidth, kHeight}, 147cb93a386Sopenharmony_ci GrMipmapped::kNo, 148cb93a386Sopenharmony_ci texOrigin, 149cb93a386Sopenharmony_ci kRGBA_8888_SkColorType, 150cb93a386Sopenharmony_ci kPremul_SkAlphaType, 151cb93a386Sopenharmony_ci nullptr, 152cb93a386Sopenharmony_ci PromiseTextureChecker::Fulfill, 153cb93a386Sopenharmony_ci PromiseTextureChecker::Release, 154cb93a386Sopenharmony_ci &promiseChecker)); 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight); 157cb93a386Sopenharmony_ci sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info); 158cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci canvas->drawImage(refImg, 0, 0); 161cb93a386Sopenharmony_ci check_unfulfilled(promiseChecker, reporter); 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ci surface->flushAndSubmit(); 164cb93a386Sopenharmony_ci // We still own the image so we should not have called Release or Done. 165cb93a386Sopenharmony_ci check_only_fulfilled(reporter, promiseChecker); 166cb93a386Sopenharmony_ci 167cb93a386Sopenharmony_ci ctx->submit(true); 168cb93a386Sopenharmony_ci check_only_fulfilled(reporter, promiseChecker); 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci canvas->drawImage(refImg, 0, 0); 171cb93a386Sopenharmony_ci canvas->drawImage(refImg, 0, 0); 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ci surface->flushAndSubmit(true); 174cb93a386Sopenharmony_ci 175cb93a386Sopenharmony_ci // Image should still be fulfilled from the first time we drew/flushed it. 176cb93a386Sopenharmony_ci check_only_fulfilled(reporter, promiseChecker); 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_ci canvas->drawImage(refImg, 0, 0); 179cb93a386Sopenharmony_ci surface->flushAndSubmit(); 180cb93a386Sopenharmony_ci check_only_fulfilled(reporter, promiseChecker); 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ci canvas->drawImage(refImg, 0, 0); 183cb93a386Sopenharmony_ci refImg.reset(); 184cb93a386Sopenharmony_ci // We no longer own the image but the last draw is still unflushed. 185cb93a386Sopenharmony_ci check_only_fulfilled(reporter, promiseChecker); 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_ci surface->flushAndSubmit(); 188cb93a386Sopenharmony_ci // Flushing should have called Release. Depending on the backend and timing it may have called 189cb93a386Sopenharmony_ci // done. 190cb93a386Sopenharmony_ci check_all_flushed_but_not_synced(reporter, promiseChecker, ctx->backend()); 191cb93a386Sopenharmony_ci ctx->submit(true); 192cb93a386Sopenharmony_ci // Now Done should definitely have been called. 193cb93a386Sopenharmony_ci check_all_done(reporter, promiseChecker); 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ci ctx->deleteBackendTexture(backendTex); 196cb93a386Sopenharmony_ci} 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_ciDEF_GPUTEST(PromiseImageTextureShutdown, reporter, ctxInfo) { 199cb93a386Sopenharmony_ci const int kWidth = 10; 200cb93a386Sopenharmony_ci const int kHeight = 10; 201cb93a386Sopenharmony_ci 202cb93a386Sopenharmony_ci // Different ways of killing contexts. 203cb93a386Sopenharmony_ci using DeathFn = std::function<void(sk_gpu_test::GrContextFactory*, GrDirectContext*)>; 204cb93a386Sopenharmony_ci DeathFn destroy = [](sk_gpu_test::GrContextFactory* factory, GrDirectContext*) { 205cb93a386Sopenharmony_ci factory->destroyContexts(); 206cb93a386Sopenharmony_ci }; 207cb93a386Sopenharmony_ci DeathFn abandon = [](sk_gpu_test::GrContextFactory* factory, GrDirectContext* dContext) { 208cb93a386Sopenharmony_ci dContext->abandonContext(); 209cb93a386Sopenharmony_ci }; 210cb93a386Sopenharmony_ci DeathFn releaseResourcesAndAbandon = [](sk_gpu_test::GrContextFactory* factory, 211cb93a386Sopenharmony_ci GrDirectContext* dContext) { 212cb93a386Sopenharmony_ci dContext->releaseResourcesAndAbandonContext(); 213cb93a386Sopenharmony_ci }; 214cb93a386Sopenharmony_ci 215cb93a386Sopenharmony_ci for (int type = 0; type < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++type) { 216cb93a386Sopenharmony_ci auto contextType = static_cast<sk_gpu_test::GrContextFactory::ContextType>(type); 217cb93a386Sopenharmony_ci // These tests are difficult to get working with Vulkan. See http://skbug.com/8705 218cb93a386Sopenharmony_ci // and http://skbug.com/8275 219cb93a386Sopenharmony_ci // Also problematic on Dawn; see http://skbug.com/10326 220cb93a386Sopenharmony_ci // And Direct3D, for similar reasons. 221cb93a386Sopenharmony_ci GrBackendApi api = sk_gpu_test::GrContextFactory::ContextTypeBackend(contextType); 222cb93a386Sopenharmony_ci if (api == GrBackendApi::kVulkan || api == GrBackendApi::kDawn || 223cb93a386Sopenharmony_ci api == GrBackendApi::kDirect3D) { 224cb93a386Sopenharmony_ci continue; 225cb93a386Sopenharmony_ci } 226cb93a386Sopenharmony_ci DeathFn contextKillers[] = {destroy, abandon, releaseResourcesAndAbandon}; 227cb93a386Sopenharmony_ci for (const DeathFn& contextDeath : contextKillers) { 228cb93a386Sopenharmony_ci sk_gpu_test::GrContextFactory factory; 229cb93a386Sopenharmony_ci auto ctx = factory.get(contextType); 230cb93a386Sopenharmony_ci if (!ctx) { 231cb93a386Sopenharmony_ci continue; 232cb93a386Sopenharmony_ci } 233cb93a386Sopenharmony_ci 234cb93a386Sopenharmony_ci auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(ctx, 235cb93a386Sopenharmony_ci kWidth, 236cb93a386Sopenharmony_ci kHeight, 237cb93a386Sopenharmony_ci kAlpha_8_SkColorType, 238cb93a386Sopenharmony_ci GrMipmapped::kNo, 239cb93a386Sopenharmony_ci GrRenderable::kNo); 240cb93a386Sopenharmony_ci if (!mbet) { 241cb93a386Sopenharmony_ci ERRORF(reporter, "Could not create texture alpha texture."); 242cb93a386Sopenharmony_ci continue; 243cb93a386Sopenharmony_ci } 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, 246cb93a386Sopenharmony_ci kPremul_SkAlphaType); 247cb93a386Sopenharmony_ci sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info); 248cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci PromiseTextureChecker promiseChecker(mbet->texture(), reporter, false); 251cb93a386Sopenharmony_ci sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(ctx->threadSafeProxy(), 252cb93a386Sopenharmony_ci mbet->texture().getBackendFormat(), 253cb93a386Sopenharmony_ci {kWidth, kHeight}, 254cb93a386Sopenharmony_ci GrMipmapped::kNo, 255cb93a386Sopenharmony_ci kTopLeft_GrSurfaceOrigin, 256cb93a386Sopenharmony_ci kAlpha_8_SkColorType, 257cb93a386Sopenharmony_ci kPremul_SkAlphaType, 258cb93a386Sopenharmony_ci /*color space*/ nullptr, 259cb93a386Sopenharmony_ci PromiseTextureChecker::Fulfill, 260cb93a386Sopenharmony_ci PromiseTextureChecker::Release, 261cb93a386Sopenharmony_ci &promiseChecker)); 262cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, image); 263cb93a386Sopenharmony_ci 264cb93a386Sopenharmony_ci canvas->drawImage(image, 0, 0); 265cb93a386Sopenharmony_ci image.reset(); 266cb93a386Sopenharmony_ci // If the surface still holds a ref to the context then the factory will not be able 267cb93a386Sopenharmony_ci // to destroy the context (and instead will release-all-and-abandon). 268cb93a386Sopenharmony_ci surface.reset(); 269cb93a386Sopenharmony_ci 270cb93a386Sopenharmony_ci ctx->flushAndSubmit(); 271cb93a386Sopenharmony_ci contextDeath(&factory, ctx); 272cb93a386Sopenharmony_ci 273cb93a386Sopenharmony_ci check_all_done(reporter, promiseChecker); 274cb93a386Sopenharmony_ci } 275cb93a386Sopenharmony_ci } 276cb93a386Sopenharmony_ci} 277cb93a386Sopenharmony_ci 278cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureFullCache, reporter, ctxInfo) { 279cb93a386Sopenharmony_ci const int kWidth = 10; 280cb93a386Sopenharmony_ci const int kHeight = 10; 281cb93a386Sopenharmony_ci 282cb93a386Sopenharmony_ci auto dContext = ctxInfo.directContext(); 283cb93a386Sopenharmony_ci 284cb93a386Sopenharmony_ci GrBackendTexture backendTex = dContext->createBackendTexture( 285cb93a386Sopenharmony_ci kWidth, kHeight, kAlpha_8_SkColorType, 286cb93a386Sopenharmony_ci SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo, GrProtected::kNo); 287cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, backendTex.isValid()); 288cb93a386Sopenharmony_ci 289cb93a386Sopenharmony_ci SkImageInfo info = 290cb93a386Sopenharmony_ci SkImageInfo::Make(kWidth, kHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType); 291cb93a386Sopenharmony_ci sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info); 292cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 293cb93a386Sopenharmony_ci 294cb93a386Sopenharmony_ci PromiseTextureChecker promiseChecker(backendTex, reporter, false); 295cb93a386Sopenharmony_ci sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(dContext->threadSafeProxy(), 296cb93a386Sopenharmony_ci backendTex.getBackendFormat(), 297cb93a386Sopenharmony_ci {kWidth, kHeight}, 298cb93a386Sopenharmony_ci GrMipmapped::kNo, 299cb93a386Sopenharmony_ci kTopLeft_GrSurfaceOrigin, 300cb93a386Sopenharmony_ci kAlpha_8_SkColorType, 301cb93a386Sopenharmony_ci kPremul_SkAlphaType, 302cb93a386Sopenharmony_ci nullptr, 303cb93a386Sopenharmony_ci PromiseTextureChecker::Fulfill, 304cb93a386Sopenharmony_ci PromiseTextureChecker::Release, 305cb93a386Sopenharmony_ci &promiseChecker)); 306cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, image); 307cb93a386Sopenharmony_ci 308cb93a386Sopenharmony_ci // Make the cache full. This tests that we don't preemptively purge cached textures for 309cb93a386Sopenharmony_ci // fulfillment due to cache pressure. 310cb93a386Sopenharmony_ci static constexpr int kMaxBytes = 1; 311cb93a386Sopenharmony_ci dContext->setResourceCacheLimit(kMaxBytes); 312cb93a386Sopenharmony_ci SkTArray<sk_sp<GrTexture>> textures; 313cb93a386Sopenharmony_ci for (int i = 0; i < 5; ++i) { 314cb93a386Sopenharmony_ci auto format = dContext->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888, 315cb93a386Sopenharmony_ci GrRenderable::kNo); 316cb93a386Sopenharmony_ci textures.emplace_back(dContext->priv().resourceProvider()->createTexture( 317cb93a386Sopenharmony_ci {100, 100}, format, GrTextureType::k2D, GrRenderable::kNo, 1, GrMipmapped::kNo, 318cb93a386Sopenharmony_ci SkBudgeted::kYes, GrProtected::kNo)); 319cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, textures[i]); 320cb93a386Sopenharmony_ci } 321cb93a386Sopenharmony_ci 322cb93a386Sopenharmony_ci size_t bytesUsed; 323cb93a386Sopenharmony_ci 324cb93a386Sopenharmony_ci dContext->getResourceCacheUsage(nullptr, &bytesUsed); 325cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bytesUsed > kMaxBytes); 326cb93a386Sopenharmony_ci 327cb93a386Sopenharmony_ci // Relying on the asserts in the promiseImageChecker to ensure that fulfills and releases are 328cb93a386Sopenharmony_ci // properly ordered. 329cb93a386Sopenharmony_ci canvas->drawImage(image, 0, 0); 330cb93a386Sopenharmony_ci surface->flushAndSubmit(); 331cb93a386Sopenharmony_ci canvas->drawImage(image, 1, 0); 332cb93a386Sopenharmony_ci surface->flushAndSubmit(); 333cb93a386Sopenharmony_ci canvas->drawImage(image, 2, 0); 334cb93a386Sopenharmony_ci surface->flushAndSubmit(); 335cb93a386Sopenharmony_ci canvas->drawImage(image, 3, 0); 336cb93a386Sopenharmony_ci surface->flushAndSubmit(); 337cb93a386Sopenharmony_ci canvas->drawImage(image, 4, 0); 338cb93a386Sopenharmony_ci surface->flushAndSubmit(); 339cb93a386Sopenharmony_ci canvas->drawImage(image, 5, 0); 340cb93a386Sopenharmony_ci surface->flushAndSubmit(); 341cb93a386Sopenharmony_ci // Must call these to ensure that all callbacks are performed before the checker is destroyed. 342cb93a386Sopenharmony_ci image.reset(); 343cb93a386Sopenharmony_ci dContext->flushAndSubmit(true); 344cb93a386Sopenharmony_ci 345cb93a386Sopenharmony_ci dContext->deleteBackendTexture(backendTex); 346cb93a386Sopenharmony_ci} 347cb93a386Sopenharmony_ci 348cb93a386Sopenharmony_ci// Test case where promise image fulfill returns nullptr. 349cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageNullFulfill, reporter, ctxInfo) { 350cb93a386Sopenharmony_ci const int kWidth = 10; 351cb93a386Sopenharmony_ci const int kHeight = 10; 352cb93a386Sopenharmony_ci 353cb93a386Sopenharmony_ci auto dContext = ctxInfo.directContext(); 354cb93a386Sopenharmony_ci 355cb93a386Sopenharmony_ci GrBackendFormat backendFormat = 356cb93a386Sopenharmony_ci dContext->defaultBackendFormat(kRGBA_8888_SkColorType, GrRenderable::kYes); 357cb93a386Sopenharmony_ci if (!backendFormat.isValid()) { 358cb93a386Sopenharmony_ci ERRORF(reporter, "No valid default kRGBA_8888 texture format."); 359cb93a386Sopenharmony_ci return; 360cb93a386Sopenharmony_ci } 361cb93a386Sopenharmony_ci 362cb93a386Sopenharmony_ci struct Counts { 363cb93a386Sopenharmony_ci int fFulfillCount = 0; 364cb93a386Sopenharmony_ci int fReleaseCount = 0; 365cb93a386Sopenharmony_ci } counts; 366cb93a386Sopenharmony_ci auto fulfill = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) { 367cb93a386Sopenharmony_ci ++static_cast<Counts*>(ctx)->fFulfillCount; 368cb93a386Sopenharmony_ci return sk_sp<SkPromiseImageTexture>(); 369cb93a386Sopenharmony_ci }; 370cb93a386Sopenharmony_ci auto release = [](SkDeferredDisplayListRecorder::PromiseImageTextureContext ctx) { 371cb93a386Sopenharmony_ci ++static_cast<Counts*>(ctx)->fReleaseCount; 372cb93a386Sopenharmony_ci }; 373cb93a386Sopenharmony_ci GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin; 374cb93a386Sopenharmony_ci sk_sp<SkImage> refImg(SkImage_Gpu::MakePromiseTexture(dContext->threadSafeProxy(), 375cb93a386Sopenharmony_ci backendFormat, 376cb93a386Sopenharmony_ci {kWidth, kHeight}, 377cb93a386Sopenharmony_ci GrMipmapped::kNo, 378cb93a386Sopenharmony_ci texOrigin, 379cb93a386Sopenharmony_ci kRGBA_8888_SkColorType, 380cb93a386Sopenharmony_ci kPremul_SkAlphaType, 381cb93a386Sopenharmony_ci nullptr, 382cb93a386Sopenharmony_ci fulfill, 383cb93a386Sopenharmony_ci release, 384cb93a386Sopenharmony_ci &counts)); 385cb93a386Sopenharmony_ci 386cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight); 387cb93a386Sopenharmony_ci sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info); 388cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 389cb93a386Sopenharmony_ci // Draw the image a few different ways. 390cb93a386Sopenharmony_ci canvas->drawImage(refImg, 0, 0); 391cb93a386Sopenharmony_ci SkPaint paint; 392cb93a386Sopenharmony_ci paint.setColorFilter(SkColorFilters::LinearToSRGBGamma()); 393cb93a386Sopenharmony_ci canvas->drawImage(refImg, 0, 0, SkSamplingOptions(), &paint); 394cb93a386Sopenharmony_ci auto shader = refImg->makeShader(SkSamplingOptions()); 395cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, shader); 396cb93a386Sopenharmony_ci paint.setShader(std::move(shader)); 397cb93a386Sopenharmony_ci canvas->drawRect(SkRect::MakeWH(1,1), paint); 398cb93a386Sopenharmony_ci paint.setShader(nullptr); 399cb93a386Sopenharmony_ci refImg.reset(); 400cb93a386Sopenharmony_ci surface->flushAndSubmit(); 401cb93a386Sopenharmony_ci // We should only call each callback once and we should have made all the calls by this point. 402cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, counts.fFulfillCount == 1); 403cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, counts.fReleaseCount == 1); 404cb93a386Sopenharmony_ci} 405