1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2019 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 "src/gpu/GrDirectContextPriv.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/gpu/GrContextThreadSafeProxy.h" 11cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 12cb93a386Sopenharmony_ci#include "src/core/SkRuntimeEffectPriv.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrContextThreadSafeProxyPriv.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrDrawingManager.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrMemoryPool.h" 17cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h" 18cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h" 19cb93a386Sopenharmony_ci#include "src/gpu/GrThreadSafePipelineBuilder.h" 20cb93a386Sopenharmony_ci#include "src/gpu/GrTracing.h" 21cb93a386Sopenharmony_ci#include "src/gpu/SkGr.h" 22cb93a386Sopenharmony_ci#include "src/gpu/SurfaceContext.h" 23cb93a386Sopenharmony_ci#include "src/gpu/SurfaceFillContext.h" 24cb93a386Sopenharmony_ci#include "src/gpu/effects/GrSkSLFP.h" 25cb93a386Sopenharmony_ci#include "src/gpu/effects/GrTextureEffect.h" 26cb93a386Sopenharmony_ci#include "src/gpu/text/GrAtlasManager.h" 27cb93a386Sopenharmony_ci#include "src/gpu/text/GrTextBlobCache.h" 28cb93a386Sopenharmony_ci#include "src/image/SkImage_Base.h" 29cb93a386Sopenharmony_ci#include "src/image/SkImage_Gpu.h" 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_ci#define ASSERT_OWNED_PROXY(P) \ 32cb93a386Sopenharmony_ci SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == this->context()) 33cb93a386Sopenharmony_ci#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(this->context()->singleOwner()) 34cb93a386Sopenharmony_ci#define RETURN_VALUE_IF_ABANDONED(value) if (this->context()->abandoned()) { return (value); } 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ciGrSemaphoresSubmitted GrDirectContextPriv::flushSurfaces( 37cb93a386Sopenharmony_ci SkSpan<GrSurfaceProxy*> proxies, 38cb93a386Sopenharmony_ci SkSurface::BackendSurfaceAccess access, 39cb93a386Sopenharmony_ci const GrFlushInfo& info, 40cb93a386Sopenharmony_ci const GrBackendSurfaceMutableState* newState) { 41cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 42cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("GrDirectContextPriv", "flushSurfaces", this->context()); 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci if (this->context()->abandoned()) { 45cb93a386Sopenharmony_ci if (info.fSubmittedProc) { 46cb93a386Sopenharmony_ci info.fSubmittedProc(info.fSubmittedContext, false); 47cb93a386Sopenharmony_ci } 48cb93a386Sopenharmony_ci if (info.fFinishedProc) { 49cb93a386Sopenharmony_ci info.fFinishedProc(info.fFinishedContext); 50cb93a386Sopenharmony_ci } 51cb93a386Sopenharmony_ci return GrSemaphoresSubmitted::kNo; 52cb93a386Sopenharmony_ci } 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci#ifdef SK_DEBUG 55cb93a386Sopenharmony_ci for (GrSurfaceProxy* proxy : proxies) { 56cb93a386Sopenharmony_ci SkASSERT(proxy); 57cb93a386Sopenharmony_ci ASSERT_OWNED_PROXY(proxy); 58cb93a386Sopenharmony_ci } 59cb93a386Sopenharmony_ci#endif 60cb93a386Sopenharmony_ci return this->context()->drawingManager()->flushSurfaces(proxies, access, info, newState); 61cb93a386Sopenharmony_ci} 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_civoid GrDirectContextPriv::createDDLTask(sk_sp<const SkDeferredDisplayList> ddl, 64cb93a386Sopenharmony_ci sk_sp<GrRenderTargetProxy> newDest, 65cb93a386Sopenharmony_ci SkIPoint offset) { 66cb93a386Sopenharmony_ci this->context()->drawingManager()->createDDLTask(std::move(ddl), std::move(newDest), offset); 67cb93a386Sopenharmony_ci} 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_cibool GrDirectContextPriv::compile(const GrProgramDesc& desc, const GrProgramInfo& info) { 70cb93a386Sopenharmony_ci GrGpu* gpu = this->getGpu(); 71cb93a386Sopenharmony_ci if (!gpu) { 72cb93a386Sopenharmony_ci return false; 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci return gpu->compile(desc, info); 76cb93a386Sopenharmony_ci} 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 80cb93a386Sopenharmony_ci#if GR_TEST_UTILS 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_civoid GrDirectContextPriv::dumpCacheStats(SkString* out) const { 83cb93a386Sopenharmony_ci#if GR_CACHE_STATS 84cb93a386Sopenharmony_ci this->context()->fResourceCache->dumpStats(out); 85cb93a386Sopenharmony_ci#endif 86cb93a386Sopenharmony_ci} 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_civoid GrDirectContextPriv::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys, 89cb93a386Sopenharmony_ci SkTArray<double>* values) const { 90cb93a386Sopenharmony_ci#if GR_CACHE_STATS 91cb93a386Sopenharmony_ci this->context()->fResourceCache->dumpStatsKeyValuePairs(keys, values); 92cb93a386Sopenharmony_ci#endif 93cb93a386Sopenharmony_ci} 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_civoid GrDirectContextPriv::printCacheStats() const { 96cb93a386Sopenharmony_ci SkString out; 97cb93a386Sopenharmony_ci this->dumpCacheStats(&out); 98cb93a386Sopenharmony_ci SkDebugf("%s", out.c_str()); 99cb93a386Sopenharmony_ci} 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci///////////////////////////////////////////////// 102cb93a386Sopenharmony_civoid GrDirectContextPriv::resetGpuStats() const { 103cb93a386Sopenharmony_ci#if GR_GPU_STATS 104cb93a386Sopenharmony_ci this->context()->fGpu->stats()->reset(); 105cb93a386Sopenharmony_ci#endif 106cb93a386Sopenharmony_ci} 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_civoid GrDirectContextPriv::dumpGpuStats(SkString* out) const { 109cb93a386Sopenharmony_ci#if GR_GPU_STATS 110cb93a386Sopenharmony_ci this->context()->fGpu->stats()->dump(out); 111cb93a386Sopenharmony_ci#ifdef SKIA_DFX_FOR_OHOS 112cb93a386Sopenharmony_ci this->context()->fResourceCache->dumpInfo(out); 113cb93a386Sopenharmony_ci#endif 114cb93a386Sopenharmony_ci if (auto builder = this->context()->fGpu->pipelineBuilder()) { 115cb93a386Sopenharmony_ci builder->stats()->dump(out); 116cb93a386Sopenharmony_ci } 117cb93a386Sopenharmony_ci#endif 118cb93a386Sopenharmony_ci} 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_civoid GrDirectContextPriv::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys, 121cb93a386Sopenharmony_ci SkTArray<double>* values) const { 122cb93a386Sopenharmony_ci#if GR_GPU_STATS 123cb93a386Sopenharmony_ci this->context()->fGpu->stats()->dumpKeyValuePairs(keys, values); 124cb93a386Sopenharmony_ci if (auto builder = this->context()->fGpu->pipelineBuilder()) { 125cb93a386Sopenharmony_ci builder->stats()->dumpKeyValuePairs(keys, values); 126cb93a386Sopenharmony_ci } 127cb93a386Sopenharmony_ci#endif 128cb93a386Sopenharmony_ci} 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_civoid GrDirectContextPriv::printGpuStats() const { 131cb93a386Sopenharmony_ci SkString out; 132cb93a386Sopenharmony_ci this->dumpGpuStats(&out); 133cb93a386Sopenharmony_ci SkDebugf("%s", out.c_str()); 134cb93a386Sopenharmony_ci} 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci///////////////////////////////////////////////// 137cb93a386Sopenharmony_civoid GrDirectContextPriv::resetContextStats() { 138cb93a386Sopenharmony_ci#if GR_GPU_STATS 139cb93a386Sopenharmony_ci this->context()->stats()->reset(); 140cb93a386Sopenharmony_ci#endif 141cb93a386Sopenharmony_ci} 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_civoid GrDirectContextPriv::dumpContextStats(SkString* out) const { 144cb93a386Sopenharmony_ci#if GR_GPU_STATS 145cb93a386Sopenharmony_ci this->context()->stats()->dump(out); 146cb93a386Sopenharmony_ci#endif 147cb93a386Sopenharmony_ci} 148cb93a386Sopenharmony_ci 149cb93a386Sopenharmony_civoid GrDirectContextPriv::dumpContextStatsKeyValuePairs(SkTArray<SkString>* keys, 150cb93a386Sopenharmony_ci SkTArray<double>* values) const { 151cb93a386Sopenharmony_ci#if GR_GPU_STATS 152cb93a386Sopenharmony_ci this->context()->stats()->dumpKeyValuePairs(keys, values); 153cb93a386Sopenharmony_ci#endif 154cb93a386Sopenharmony_ci} 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_civoid GrDirectContextPriv::printContextStats() const { 157cb93a386Sopenharmony_ci SkString out; 158cb93a386Sopenharmony_ci this->dumpContextStats(&out); 159cb93a386Sopenharmony_ci SkDebugf("%s", out.c_str()); 160cb93a386Sopenharmony_ci} 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci///////////////////////////////////////////////// 163cb93a386Sopenharmony_cisk_sp<SkImage> GrDirectContextPriv::testingOnly_getFontAtlasImage(GrMaskFormat format, 164cb93a386Sopenharmony_ci unsigned int index) { 165cb93a386Sopenharmony_ci auto atlasManager = this->getAtlasManager(); 166cb93a386Sopenharmony_ci if (!atlasManager) { 167cb93a386Sopenharmony_ci return nullptr; 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci unsigned int numActiveProxies; 171cb93a386Sopenharmony_ci const GrSurfaceProxyView* views = atlasManager->getViews(format, &numActiveProxies); 172cb93a386Sopenharmony_ci if (index >= numActiveProxies || !views || !views[index].proxy()) { 173cb93a386Sopenharmony_ci return nullptr; 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_ci SkColorType colorType = GrColorTypeToSkColorType(GrMaskFormatToColorType(format)); 177cb93a386Sopenharmony_ci SkASSERT(views[index].proxy()->priv().isExact()); 178cb93a386Sopenharmony_ci return sk_make_sp<SkImage_Gpu>(sk_ref_sp(this->context()), 179cb93a386Sopenharmony_ci kNeedNewImageUniqueID, 180cb93a386Sopenharmony_ci views[index], 181cb93a386Sopenharmony_ci SkColorInfo(colorType, kPremul_SkAlphaType, nullptr)); 182cb93a386Sopenharmony_ci} 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_civoid GrDirectContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject( 185cb93a386Sopenharmony_ci GrOnFlushCallbackObject* cb) { 186cb93a386Sopenharmony_ci this->context()->flushAndSubmit(); 187cb93a386Sopenharmony_ci this->context()->drawingManager()->testingOnly_removeOnFlushCallbackObject(cb); 188cb93a386Sopenharmony_ci} 189cb93a386Sopenharmony_ci#endif 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_ci// Both of these effects aggressively round to the nearest exact (N / 255) floating point values. 192cb93a386Sopenharmony_ci// This lets us find a round-trip preserving pair on some GPUs that do odd byte to float conversion. 193cb93a386Sopenharmony_cistatic std::unique_ptr<GrFragmentProcessor> make_premul_effect( 194cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> fp) { 195cb93a386Sopenharmony_ci if (!fp) { 196cb93a386Sopenharmony_ci return nullptr; 197cb93a386Sopenharmony_ci } 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ci static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter, R"( 200cb93a386Sopenharmony_ci half4 main(half4 halfColor) { 201cb93a386Sopenharmony_ci float4 color = float4(halfColor); 202cb93a386Sopenharmony_ci color = floor(color * 255 + 0.5) / 255; 203cb93a386Sopenharmony_ci color.rgb = floor(color.rgb * color.a * 255 + 0.5) / 255; 204cb93a386Sopenharmony_ci return color; 205cb93a386Sopenharmony_ci } 206cb93a386Sopenharmony_ci )"); 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci fp = GrSkSLFP::Make(effect, "ToPremul", std::move(fp), GrSkSLFP::OptFlags::kNone); 209cb93a386Sopenharmony_ci return GrFragmentProcessor::HighPrecision(std::move(fp)); 210cb93a386Sopenharmony_ci} 211cb93a386Sopenharmony_ci 212cb93a386Sopenharmony_cistatic std::unique_ptr<GrFragmentProcessor> make_unpremul_effect( 213cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> fp) { 214cb93a386Sopenharmony_ci if (!fp) { 215cb93a386Sopenharmony_ci return nullptr; 216cb93a386Sopenharmony_ci } 217cb93a386Sopenharmony_ci 218cb93a386Sopenharmony_ci static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter, R"( 219cb93a386Sopenharmony_ci half4 main(half4 halfColor) { 220cb93a386Sopenharmony_ci float4 color = float4(halfColor); 221cb93a386Sopenharmony_ci color = floor(color * 255 + 0.5) / 255; 222cb93a386Sopenharmony_ci color.rgb = color.a <= 0 ? half3(0) : floor(color.rgb / color.a * 255 + 0.5) / 255; 223cb93a386Sopenharmony_ci return color; 224cb93a386Sopenharmony_ci } 225cb93a386Sopenharmony_ci )"); 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ci fp = GrSkSLFP::Make(effect, "ToUnpremul", std::move(fp), GrSkSLFP::OptFlags::kNone); 228cb93a386Sopenharmony_ci return GrFragmentProcessor::HighPrecision(std::move(fp)); 229cb93a386Sopenharmony_ci} 230cb93a386Sopenharmony_ci 231cb93a386Sopenharmony_cistatic bool test_for_preserving_PM_conversions(GrDirectContext* dContext) { 232cb93a386Sopenharmony_ci static constexpr int kSize = 256; 233cb93a386Sopenharmony_ci SkAutoTMalloc<uint32_t> data(kSize * kSize * 3); 234cb93a386Sopenharmony_ci uint32_t* srcData = data.get(); 235cb93a386Sopenharmony_ci 236cb93a386Sopenharmony_ci // Fill with every possible premultiplied A, color channel value. There will be 256-y duplicate 237cb93a386Sopenharmony_ci // values in row y. We set r, g, and b to the same value since they are handled identically. 238cb93a386Sopenharmony_ci for (int y = 0; y < kSize; ++y) { 239cb93a386Sopenharmony_ci for (int x = 0; x < kSize; ++x) { 240cb93a386Sopenharmony_ci uint8_t* color = reinterpret_cast<uint8_t*>(&srcData[kSize*y + x]); 241cb93a386Sopenharmony_ci color[3] = y; 242cb93a386Sopenharmony_ci color[2] = std::min(x, y); 243cb93a386Sopenharmony_ci color[1] = std::min(x, y); 244cb93a386Sopenharmony_ci color[0] = std::min(x, y); 245cb93a386Sopenharmony_ci } 246cb93a386Sopenharmony_ci } 247cb93a386Sopenharmony_ci 248cb93a386Sopenharmony_ci const SkImageInfo pmII = 249cb93a386Sopenharmony_ci SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType); 250cb93a386Sopenharmony_ci const SkImageInfo upmII = pmII.makeAlphaType(kUnpremul_SkAlphaType); 251cb93a386Sopenharmony_ci 252cb93a386Sopenharmony_ci auto readSFC = dContext->priv().makeSFC(upmII, SkBackingFit::kExact); 253cb93a386Sopenharmony_ci auto tempSFC = dContext->priv().makeSFC(pmII, SkBackingFit::kExact); 254cb93a386Sopenharmony_ci if (!readSFC || !tempSFC) { 255cb93a386Sopenharmony_ci return false; 256cb93a386Sopenharmony_ci } 257cb93a386Sopenharmony_ci 258cb93a386Sopenharmony_ci // This function is only ever called if we are in a GrDirectContext since we are calling read 259cb93a386Sopenharmony_ci // pixels here. Thus the pixel data will be uploaded immediately and we don't need to keep the 260cb93a386Sopenharmony_ci // pixel data alive in the proxy. Therefore the ReleaseProc is nullptr. 261cb93a386Sopenharmony_ci SkBitmap bitmap; 262cb93a386Sopenharmony_ci bitmap.installPixels(pmII, srcData, 4 * kSize); 263cb93a386Sopenharmony_ci bitmap.setImmutable(); 264cb93a386Sopenharmony_ci 265cb93a386Sopenharmony_ci auto dataView = std::get<0>(GrMakeUncachedBitmapProxyView(dContext, bitmap)); 266cb93a386Sopenharmony_ci if (!dataView) { 267cb93a386Sopenharmony_ci return false; 268cb93a386Sopenharmony_ci } 269cb93a386Sopenharmony_ci 270cb93a386Sopenharmony_ci uint32_t* firstRead = data.get() + kSize*kSize; 271cb93a386Sopenharmony_ci uint32_t* secondRead = data.get() + 2*kSize*kSize; 272cb93a386Sopenharmony_ci std::fill_n( firstRead, kSize*kSize, 0); 273cb93a386Sopenharmony_ci std::fill_n(secondRead, kSize*kSize, 0); 274cb93a386Sopenharmony_ci 275cb93a386Sopenharmony_ci GrPixmap firstReadPM( upmII, firstRead, kSize*sizeof(uint32_t)); 276cb93a386Sopenharmony_ci GrPixmap secondReadPM(upmII, secondRead, kSize*sizeof(uint32_t)); 277cb93a386Sopenharmony_ci 278cb93a386Sopenharmony_ci // We do a PM->UPM draw from dataTex to readTex and read the data. Then we do a UPM->PM draw 279cb93a386Sopenharmony_ci // from readTex to tempTex followed by a PM->UPM draw to readTex and finally read the data. 280cb93a386Sopenharmony_ci // We then verify that two reads produced the same values. 281cb93a386Sopenharmony_ci 282cb93a386Sopenharmony_ci auto fp1 = make_unpremul_effect(GrTextureEffect::Make(std::move(dataView), bitmap.alphaType())); 283cb93a386Sopenharmony_ci readSFC->fillRectWithFP(SkIRect::MakeWH(kSize, kSize), std::move(fp1)); 284cb93a386Sopenharmony_ci if (!readSFC->readPixels(dContext, firstReadPM, {0, 0})) { 285cb93a386Sopenharmony_ci return false; 286cb93a386Sopenharmony_ci } 287cb93a386Sopenharmony_ci 288cb93a386Sopenharmony_ci auto fp2 = make_premul_effect( 289cb93a386Sopenharmony_ci GrTextureEffect::Make(readSFC->readSurfaceView(), readSFC->colorInfo().alphaType())); 290cb93a386Sopenharmony_ci tempSFC->fillRectWithFP(SkIRect::MakeWH(kSize, kSize), std::move(fp2)); 291cb93a386Sopenharmony_ci 292cb93a386Sopenharmony_ci auto fp3 = make_unpremul_effect( 293cb93a386Sopenharmony_ci GrTextureEffect::Make(tempSFC->readSurfaceView(), tempSFC->colorInfo().alphaType())); 294cb93a386Sopenharmony_ci readSFC->fillRectWithFP(SkIRect::MakeWH(kSize, kSize), std::move(fp3)); 295cb93a386Sopenharmony_ci 296cb93a386Sopenharmony_ci if (!readSFC->readPixels(dContext, secondReadPM, {0, 0})) { 297cb93a386Sopenharmony_ci return false; 298cb93a386Sopenharmony_ci } 299cb93a386Sopenharmony_ci 300cb93a386Sopenharmony_ci for (int y = 0; y < kSize; ++y) { 301cb93a386Sopenharmony_ci for (int x = 0; x <= y; ++x) { 302cb93a386Sopenharmony_ci if (firstRead[kSize*y + x] != secondRead[kSize*y + x]) { 303cb93a386Sopenharmony_ci return false; 304cb93a386Sopenharmony_ci } 305cb93a386Sopenharmony_ci } 306cb93a386Sopenharmony_ci } 307cb93a386Sopenharmony_ci 308cb93a386Sopenharmony_ci return true; 309cb93a386Sopenharmony_ci} 310cb93a386Sopenharmony_ci 311cb93a386Sopenharmony_cibool GrDirectContextPriv::validPMUPMConversionExists() { 312cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 313cb93a386Sopenharmony_ci 314cb93a386Sopenharmony_ci auto dContext = this->context(); 315cb93a386Sopenharmony_ci 316cb93a386Sopenharmony_ci if (!dContext->fDidTestPMConversions) { 317cb93a386Sopenharmony_ci dContext->fPMUPMConversionsRoundTrip = test_for_preserving_PM_conversions(dContext); 318cb93a386Sopenharmony_ci dContext->fDidTestPMConversions = true; 319cb93a386Sopenharmony_ci } 320cb93a386Sopenharmony_ci 321cb93a386Sopenharmony_ci // The PM<->UPM tests fail or succeed together so we only need to check one. 322cb93a386Sopenharmony_ci return dContext->fPMUPMConversionsRoundTrip; 323cb93a386Sopenharmony_ci} 324cb93a386Sopenharmony_ci 325cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> GrDirectContextPriv::createPMToUPMEffect( 326cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> fp) { 327cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 328cb93a386Sopenharmony_ci // We should have already called this->priv().validPMUPMConversionExists() in this case 329cb93a386Sopenharmony_ci SkASSERT(this->context()->fDidTestPMConversions); 330cb93a386Sopenharmony_ci // ...and it should have succeeded 331cb93a386Sopenharmony_ci SkASSERT(this->validPMUPMConversionExists()); 332cb93a386Sopenharmony_ci 333cb93a386Sopenharmony_ci return make_unpremul_effect(std::move(fp)); 334cb93a386Sopenharmony_ci} 335cb93a386Sopenharmony_ci 336cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> GrDirectContextPriv::createUPMToPMEffect( 337cb93a386Sopenharmony_ci std::unique_ptr<GrFragmentProcessor> fp) { 338cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 339cb93a386Sopenharmony_ci // We should have already called this->priv().validPMUPMConversionExists() in this case 340cb93a386Sopenharmony_ci SkASSERT(this->context()->fDidTestPMConversions); 341cb93a386Sopenharmony_ci // ...and it should have succeeded 342cb93a386Sopenharmony_ci SkASSERT(this->validPMUPMConversionExists()); 343cb93a386Sopenharmony_ci 344cb93a386Sopenharmony_ci return make_premul_effect(std::move(fp)); 345cb93a386Sopenharmony_ci} 346