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