1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2016 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/SurfaceContext.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include <memory>
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
13cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h"
14cb93a386Sopenharmony_ci#include "src/core/SkAutoPixmapStorage.h"
15cb93a386Sopenharmony_ci#include "src/core/SkMipmap.h"
16cb93a386Sopenharmony_ci#include "src/core/SkYUVMath.h"
17cb93a386Sopenharmony_ci#include "src/gpu/GrClientMappedBufferManager.h"
18cb93a386Sopenharmony_ci#include "src/gpu/GrColorSpaceXform.h"
19cb93a386Sopenharmony_ci#include "src/gpu/GrDataUtils.h"
20cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
21cb93a386Sopenharmony_ci#include "src/gpu/GrDrawingManager.h"
22cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h"
23cb93a386Sopenharmony_ci#include "src/gpu/GrImageInfo.h"
24cb93a386Sopenharmony_ci#include "src/gpu/GrProxyProvider.h"
25cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h"
26cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h"
27cb93a386Sopenharmony_ci#include "src/gpu/GrTracing.h"
28cb93a386Sopenharmony_ci#include "src/gpu/SkGr.h"
29cb93a386Sopenharmony_ci#include "src/gpu/SurfaceFillContext.h"
30cb93a386Sopenharmony_ci#include "src/gpu/effects/GrBicubicEffect.h"
31cb93a386Sopenharmony_ci#include "src/gpu/effects/GrTextureEffect.h"
32cb93a386Sopenharmony_ci
33cb93a386Sopenharmony_ci#define ASSERT_SINGLE_OWNER         GR_ASSERT_SINGLE_OWNER(this->singleOwner())
34cb93a386Sopenharmony_ci#define RETURN_FALSE_IF_ABANDONED   if (this->fContext->abandoned()) { return false;   }
35cb93a386Sopenharmony_ci#define RETURN_NULLPTR_IF_ABANDONED if (this->fContext->abandoned()) { return nullptr; }
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_cinamespace skgpu {
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_ciSurfaceContext::SurfaceContext(GrRecordingContext* context,
40cb93a386Sopenharmony_ci                               GrSurfaceProxyView readView,
41cb93a386Sopenharmony_ci                               const GrColorInfo& info)
42cb93a386Sopenharmony_ci        : fContext(context), fReadView(std::move(readView)), fColorInfo(info) {
43cb93a386Sopenharmony_ci    SkASSERT(!context->abandoned());
44cb93a386Sopenharmony_ci}
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ciconst GrCaps* SurfaceContext::caps() const { return fContext->priv().caps(); }
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_ciGrDrawingManager* SurfaceContext::drawingManager() {
49cb93a386Sopenharmony_ci    return fContext->priv().drawingManager();
50cb93a386Sopenharmony_ci}
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_ciconst GrDrawingManager* SurfaceContext::drawingManager() const {
53cb93a386Sopenharmony_ci    return fContext->priv().drawingManager();
54cb93a386Sopenharmony_ci}
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci#ifdef SK_DEBUG
57cb93a386Sopenharmony_ciGrSingleOwner* SurfaceContext::singleOwner() const { return fContext->priv().singleOwner(); }
58cb93a386Sopenharmony_ci#endif
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_cistatic bool alpha_types_compatible(SkAlphaType srcAlphaType, SkAlphaType dstAlphaType) {
61cb93a386Sopenharmony_ci    // If both alpha types are kUnknown things make sense. If not, it's too underspecified.
62cb93a386Sopenharmony_ci    return (srcAlphaType == kUnknown_SkAlphaType) == (dstAlphaType == kUnknown_SkAlphaType);
63cb93a386Sopenharmony_ci}
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_cibool SurfaceContext::readPixels(GrDirectContext* dContext, GrPixmap dst, SkIPoint pt) {
66cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
67cb93a386Sopenharmony_ci    RETURN_FALSE_IF_ABANDONED
68cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
69cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceContext", "readPixels", fContext);
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ci    if (!fContext->priv().matches(dContext)) {
72cb93a386Sopenharmony_ci        return false;
73cb93a386Sopenharmony_ci    }
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci    if (dst.colorType() == GrColorType::kUnknown) {
76cb93a386Sopenharmony_ci        return false;
77cb93a386Sopenharmony_ci    }
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_ci    if (dst.rowBytes() % dst.info().bpp()) {
80cb93a386Sopenharmony_ci        return false;
81cb93a386Sopenharmony_ci    }
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_ci    dst = dst.clip(this->dimensions(), &pt);
84cb93a386Sopenharmony_ci    if (!dst.hasPixels()) {
85cb93a386Sopenharmony_ci        return false;
86cb93a386Sopenharmony_ci    }
87cb93a386Sopenharmony_ci    if (!alpha_types_compatible(this->colorInfo().alphaType(), dst.alphaType())) {
88cb93a386Sopenharmony_ci        return false;
89cb93a386Sopenharmony_ci    }
90cb93a386Sopenharmony_ci    // We allow unknown alpha types but only if both src and dst are unknown. Otherwise, it's too
91cb93a386Sopenharmony_ci    // weird to reason about what should be expected.
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci    sk_sp<GrSurfaceProxy> srcProxy = this->asSurfaceProxyRef();
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_ci    if (srcProxy->framebufferOnly()) {
96cb93a386Sopenharmony_ci        return false;
97cb93a386Sopenharmony_ci    }
98cb93a386Sopenharmony_ci
99cb93a386Sopenharmony_ci    // MDB TODO: delay this instantiation until later in the method
100cb93a386Sopenharmony_ci    if (!srcProxy->instantiate(dContext->priv().resourceProvider())) {
101cb93a386Sopenharmony_ci        return false;
102cb93a386Sopenharmony_ci    }
103cb93a386Sopenharmony_ci
104cb93a386Sopenharmony_ci    GrSurface* srcSurface = srcProxy->peekSurface();
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci    SkColorSpaceXformSteps::Flags flags =
107cb93a386Sopenharmony_ci            SkColorSpaceXformSteps{this->colorInfo(), dst.info()}.flags;
108cb93a386Sopenharmony_ci    bool unpremul            = flags.unpremul,
109cb93a386Sopenharmony_ci         needColorConversion = flags.linearize || flags.gamut_transform || flags.encode,
110cb93a386Sopenharmony_ci         premul              = flags.premul;
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci    const GrCaps* caps = dContext->priv().caps();
113cb93a386Sopenharmony_ci    bool srcIsCompressed = caps->isFormatCompressed(srcSurface->backendFormat());
114cb93a386Sopenharmony_ci    // This is the getImageData equivalent to the canvas2D putImageData fast path. We probably don't
115cb93a386Sopenharmony_ci    // care so much about getImageData performance. However, in order to ensure putImageData/
116cb93a386Sopenharmony_ci    // getImageData in "legacy" mode are round-trippable we use the GPU to do the complementary
117cb93a386Sopenharmony_ci    // unpremul step to writeSurfacePixels's premul step (which is determined empirically in
118cb93a386Sopenharmony_ci    // fContext->vaildaPMUPMConversionExists()).
119cb93a386Sopenharmony_ci    GrBackendFormat defaultRGBAFormat = caps->getDefaultBackendFormat(GrColorType::kRGBA_8888,
120cb93a386Sopenharmony_ci                                                                      GrRenderable::kYes);
121cb93a386Sopenharmony_ci    GrColorType srcColorType = this->colorInfo().colorType();
122cb93a386Sopenharmony_ci    bool canvas2DFastPath = unpremul && !needColorConversion &&
123cb93a386Sopenharmony_ci                            (GrColorType::kRGBA_8888 == dst.colorType() ||
124cb93a386Sopenharmony_ci                             GrColorType::kBGRA_8888 == dst.colorType()) &&
125cb93a386Sopenharmony_ci                            SkToBool(srcProxy->asTextureProxy()) &&
126cb93a386Sopenharmony_ci                            (srcColorType == GrColorType::kRGBA_8888 ||
127cb93a386Sopenharmony_ci                             srcColorType == GrColorType::kBGRA_8888) &&
128cb93a386Sopenharmony_ci                            defaultRGBAFormat.isValid() &&
129cb93a386Sopenharmony_ci                            dContext->priv().validPMUPMConversionExists();
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_ci    // Since the validPMUPMConversionExists function actually submits work to the gpu to do its
132cb93a386Sopenharmony_ci    // tests, it is possible that during that call we have abandoned the context. Thus, we do
133cb93a386Sopenharmony_ci    // another abandoned check here to make sure we are still valid.
134cb93a386Sopenharmony_ci    RETURN_FALSE_IF_ABANDONED
135cb93a386Sopenharmony_ci
136cb93a386Sopenharmony_ci    auto readFlag = caps->surfaceSupportsReadPixels(srcSurface);
137cb93a386Sopenharmony_ci    if (readFlag == GrCaps::SurfaceReadPixelsSupport::kUnsupported) {
138cb93a386Sopenharmony_ci        return false;
139cb93a386Sopenharmony_ci    }
140cb93a386Sopenharmony_ci
141cb93a386Sopenharmony_ci    if (readFlag == GrCaps::SurfaceReadPixelsSupport::kCopyToTexture2D || canvas2DFastPath) {
142cb93a386Sopenharmony_ci        std::unique_ptr<SurfaceContext> tempCtx;
143cb93a386Sopenharmony_ci        if (this->asTextureProxy()) {
144cb93a386Sopenharmony_ci            GrColorType colorType = (canvas2DFastPath || srcIsCompressed)
145cb93a386Sopenharmony_ci                                            ? GrColorType::kRGBA_8888
146cb93a386Sopenharmony_ci                                            : this->colorInfo().colorType();
147cb93a386Sopenharmony_ci            SkAlphaType alphaType = canvas2DFastPath ? dst.alphaType()
148cb93a386Sopenharmony_ci                                                     : this->colorInfo().alphaType();
149cb93a386Sopenharmony_ci            GrImageInfo tempInfo(colorType,
150cb93a386Sopenharmony_ci                                 alphaType,
151cb93a386Sopenharmony_ci                                 this->colorInfo().refColorSpace(),
152cb93a386Sopenharmony_ci                                 dst.dimensions());
153cb93a386Sopenharmony_ci            auto sfc = dContext->priv().makeSFC(tempInfo, SkBackingFit::kApprox);
154cb93a386Sopenharmony_ci            if (!sfc) {
155cb93a386Sopenharmony_ci                return false;
156cb93a386Sopenharmony_ci            }
157cb93a386Sopenharmony_ci
158cb93a386Sopenharmony_ci            std::unique_ptr<GrFragmentProcessor> fp;
159cb93a386Sopenharmony_ci            if (canvas2DFastPath) {
160cb93a386Sopenharmony_ci                fp = dContext->priv().createPMToUPMEffect(GrTextureEffect::Make(
161cb93a386Sopenharmony_ci                        this->readSurfaceView(), this->colorInfo().alphaType()));
162cb93a386Sopenharmony_ci                if (dst.colorType() == GrColorType::kBGRA_8888) {
163cb93a386Sopenharmony_ci                    fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
164cb93a386Sopenharmony_ci                    dst = GrPixmap(dst.info().makeColorType(GrColorType::kRGBA_8888),
165cb93a386Sopenharmony_ci                                   dst.addr(),
166cb93a386Sopenharmony_ci                                   dst.rowBytes());
167cb93a386Sopenharmony_ci                }
168cb93a386Sopenharmony_ci            } else {
169cb93a386Sopenharmony_ci                fp = GrTextureEffect::Make(this->readSurfaceView(), this->colorInfo().alphaType());
170cb93a386Sopenharmony_ci            }
171cb93a386Sopenharmony_ci            if (!fp) {
172cb93a386Sopenharmony_ci                return false;
173cb93a386Sopenharmony_ci            }
174cb93a386Sopenharmony_ci            sfc->fillRectToRectWithFP(SkIRect::MakePtSize(pt, dst.dimensions()),
175cb93a386Sopenharmony_ci                                      SkIRect::MakeSize(dst.dimensions()),
176cb93a386Sopenharmony_ci                                      std::move(fp));
177cb93a386Sopenharmony_ci            pt = {0, 0};
178cb93a386Sopenharmony_ci            tempCtx = std::move(sfc);
179cb93a386Sopenharmony_ci        } else {
180cb93a386Sopenharmony_ci            auto restrictions = this->caps()->getDstCopyRestrictions(this->asRenderTargetProxy(),
181cb93a386Sopenharmony_ci                                                                     this->colorInfo().colorType());
182cb93a386Sopenharmony_ci            sk_sp<GrSurfaceProxy> copy;
183cb93a386Sopenharmony_ci            static constexpr auto kFit = SkBackingFit::kExact;
184cb93a386Sopenharmony_ci            static constexpr auto kBudgeted = SkBudgeted::kYes;
185cb93a386Sopenharmony_ci            static constexpr auto kMipMapped = GrMipMapped::kNo;
186cb93a386Sopenharmony_ci            if (restrictions.fMustCopyWholeSrc) {
187cb93a386Sopenharmony_ci                copy = GrSurfaceProxy::Copy(fContext,
188cb93a386Sopenharmony_ci                                            std::move(srcProxy),
189cb93a386Sopenharmony_ci                                            this->origin(),
190cb93a386Sopenharmony_ci                                            kMipMapped,
191cb93a386Sopenharmony_ci                                            kFit,
192cb93a386Sopenharmony_ci                                            kBudgeted);
193cb93a386Sopenharmony_ci            } else {
194cb93a386Sopenharmony_ci                auto srcRect = SkIRect::MakePtSize(pt, dst.dimensions());
195cb93a386Sopenharmony_ci                copy = GrSurfaceProxy::Copy(fContext,
196cb93a386Sopenharmony_ci                                            std::move(srcProxy),
197cb93a386Sopenharmony_ci                                            this->origin(),
198cb93a386Sopenharmony_ci                                            kMipMapped,
199cb93a386Sopenharmony_ci                                            srcRect,
200cb93a386Sopenharmony_ci                                            kFit,
201cb93a386Sopenharmony_ci                                            kBudgeted,
202cb93a386Sopenharmony_ci                                            restrictions.fRectsMustMatch);
203cb93a386Sopenharmony_ci                pt = {0, 0};
204cb93a386Sopenharmony_ci            }
205cb93a386Sopenharmony_ci            if (!copy) {
206cb93a386Sopenharmony_ci                return false;
207cb93a386Sopenharmony_ci            }
208cb93a386Sopenharmony_ci            GrSurfaceProxyView view{std::move(copy), this->origin(), this->readSwizzle()};
209cb93a386Sopenharmony_ci            tempCtx = dContext->priv().makeSC(std::move(view), this->colorInfo());
210cb93a386Sopenharmony_ci            SkASSERT(tempCtx);
211cb93a386Sopenharmony_ci        }
212cb93a386Sopenharmony_ci        return tempCtx->readPixels(dContext, dst, pt);
213cb93a386Sopenharmony_ci    }
214cb93a386Sopenharmony_ci
215cb93a386Sopenharmony_ci    bool flip = this->origin() == kBottomLeft_GrSurfaceOrigin;
216cb93a386Sopenharmony_ci
217cb93a386Sopenharmony_ci    auto supportedRead = caps->supportedReadPixelsColorType(
218cb93a386Sopenharmony_ci            this->colorInfo().colorType(), srcProxy->backendFormat(), dst.colorType());
219cb93a386Sopenharmony_ci
220cb93a386Sopenharmony_ci    bool makeTight =
221cb93a386Sopenharmony_ci            !caps->readPixelsRowBytesSupport() && dst.rowBytes() != dst.info().minRowBytes();
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_ci    bool convert = unpremul || premul || needColorConversion || flip || makeTight ||
224cb93a386Sopenharmony_ci                   (dst.colorType() != supportedRead.fColorType);
225cb93a386Sopenharmony_ci
226cb93a386Sopenharmony_ci    std::unique_ptr<char[]> tmpPixels;
227cb93a386Sopenharmony_ci    GrPixmap tmp;
228cb93a386Sopenharmony_ci    void* readDst = dst.addr();
229cb93a386Sopenharmony_ci    size_t readRB = dst.rowBytes();
230cb93a386Sopenharmony_ci    if (convert) {
231cb93a386Sopenharmony_ci        GrImageInfo tmpInfo(supportedRead.fColorType,
232cb93a386Sopenharmony_ci                            this->colorInfo().alphaType(),
233cb93a386Sopenharmony_ci                            this->colorInfo().refColorSpace(),
234cb93a386Sopenharmony_ci                            dst.dimensions());
235cb93a386Sopenharmony_ci        size_t tmpRB = tmpInfo.minRowBytes();
236cb93a386Sopenharmony_ci        size_t size = tmpRB * tmpInfo.height();
237cb93a386Sopenharmony_ci        // Chrome MSAN bots require the data to be initialized (hence the ()).
238cb93a386Sopenharmony_ci        tmpPixels = std::make_unique<char[]>(size);
239cb93a386Sopenharmony_ci        tmp = {tmpInfo, tmpPixels.get(), tmpRB};
240cb93a386Sopenharmony_ci
241cb93a386Sopenharmony_ci        readDst = tmpPixels.get();
242cb93a386Sopenharmony_ci        readRB = tmpRB;
243cb93a386Sopenharmony_ci        pt.fY = flip ? srcSurface->height() - pt.fY - dst.height() : pt.fY;
244cb93a386Sopenharmony_ci    }
245cb93a386Sopenharmony_ci
246cb93a386Sopenharmony_ci    dContext->priv().flushSurface(srcProxy.get());
247cb93a386Sopenharmony_ci    dContext->submit();
248cb93a386Sopenharmony_ci    if (!dContext->priv().getGpu()->readPixels(srcSurface,
249cb93a386Sopenharmony_ci                                               SkIRect::MakePtSize(pt, dst.dimensions()),
250cb93a386Sopenharmony_ci                                               this->colorInfo().colorType(),
251cb93a386Sopenharmony_ci                                               supportedRead.fColorType,
252cb93a386Sopenharmony_ci                                               readDst,
253cb93a386Sopenharmony_ci                                               readRB)) {
254cb93a386Sopenharmony_ci        return false;
255cb93a386Sopenharmony_ci    }
256cb93a386Sopenharmony_ci
257cb93a386Sopenharmony_ci    if (tmp.hasPixels()) {
258cb93a386Sopenharmony_ci        return GrConvertPixels(dst, tmp, flip);
259cb93a386Sopenharmony_ci    }
260cb93a386Sopenharmony_ci    return true;
261cb93a386Sopenharmony_ci}
262cb93a386Sopenharmony_ci
263cb93a386Sopenharmony_cibool SurfaceContext::writePixels(GrDirectContext* dContext,
264cb93a386Sopenharmony_ci                                 GrCPixmap src,
265cb93a386Sopenharmony_ci                                 SkIPoint dstPt) {
266cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
267cb93a386Sopenharmony_ci    RETURN_FALSE_IF_ABANDONED
268cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
269cb93a386Sopenharmony_ci
270cb93a386Sopenharmony_ci    src = src.clip(this->dimensions(), &dstPt);
271cb93a386Sopenharmony_ci    if (!src.hasPixels()) {
272cb93a386Sopenharmony_ci        return false;
273cb93a386Sopenharmony_ci    }
274cb93a386Sopenharmony_ci    if (!src.info().bpp() || src.rowBytes() % src.info().bpp()) {
275cb93a386Sopenharmony_ci        return false;
276cb93a386Sopenharmony_ci    }
277cb93a386Sopenharmony_ci    return this->internalWritePixels(dContext, &src, 1, dstPt);
278cb93a386Sopenharmony_ci}
279cb93a386Sopenharmony_ci
280cb93a386Sopenharmony_cibool SurfaceContext::writePixels(GrDirectContext* dContext,
281cb93a386Sopenharmony_ci                                 const GrCPixmap src[],
282cb93a386Sopenharmony_ci                                 int numLevels) {
283cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
284cb93a386Sopenharmony_ci    RETURN_FALSE_IF_ABANDONED
285cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
286cb93a386Sopenharmony_ci
287cb93a386Sopenharmony_ci    SkASSERT(dContext);
288cb93a386Sopenharmony_ci    SkASSERT(numLevels >= 1);
289cb93a386Sopenharmony_ci    SkASSERT(src);
290cb93a386Sopenharmony_ci
291cb93a386Sopenharmony_ci    if (numLevels == 1) {
292cb93a386Sopenharmony_ci        if (src->dimensions() != this->dimensions()) {
293cb93a386Sopenharmony_ci            return false;
294cb93a386Sopenharmony_ci        }
295cb93a386Sopenharmony_ci        return this->writePixels(dContext, src[0], {0, 0});
296cb93a386Sopenharmony_ci    }
297cb93a386Sopenharmony_ci    if (!this->asTextureProxy() || this->asTextureProxy()->proxyMipmapped() == GrMipmapped::kNo) {
298cb93a386Sopenharmony_ci        return false;
299cb93a386Sopenharmony_ci    }
300cb93a386Sopenharmony_ci
301cb93a386Sopenharmony_ci    SkISize dims = this->dimensions();
302cb93a386Sopenharmony_ci    if (numLevels != SkMipmap::ComputeLevelCount(dims) + 1) {
303cb93a386Sopenharmony_ci        return false;
304cb93a386Sopenharmony_ci    }
305cb93a386Sopenharmony_ci    for (int i = 0; i < numLevels; ++i) {
306cb93a386Sopenharmony_ci        if (src[i].colorInfo() != src[0].colorInfo()) {
307cb93a386Sopenharmony_ci            return false;
308cb93a386Sopenharmony_ci        }
309cb93a386Sopenharmony_ci        if (dims != src[i].dimensions()) {
310cb93a386Sopenharmony_ci            return false;
311cb93a386Sopenharmony_ci        }
312cb93a386Sopenharmony_ci        if (!src[i].info().bpp() || src[i].rowBytes() % src[i].info().bpp()) {
313cb93a386Sopenharmony_ci            return false;
314cb93a386Sopenharmony_ci        }
315cb93a386Sopenharmony_ci        dims = {std::max(1, dims.width()/2), std::max(1, dims.height()/2)};
316cb93a386Sopenharmony_ci    }
317cb93a386Sopenharmony_ci    return this->internalWritePixels(dContext, src, numLevels, {0, 0});
318cb93a386Sopenharmony_ci}
319cb93a386Sopenharmony_ci
320cb93a386Sopenharmony_cibool SurfaceContext::internalWritePixels(GrDirectContext* dContext,
321cb93a386Sopenharmony_ci                                         const GrCPixmap src[],
322cb93a386Sopenharmony_ci                                         int numLevels,
323cb93a386Sopenharmony_ci                                         SkIPoint pt) {
324cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceContext", "internalWritePixels", fContext);
325cb93a386Sopenharmony_ci
326cb93a386Sopenharmony_ci    SkASSERT(numLevels >= 1);
327cb93a386Sopenharmony_ci    SkASSERT(src);
328cb93a386Sopenharmony_ci
329cb93a386Sopenharmony_ci    // We can either write to a subset or write MIP levels, but not both.
330cb93a386Sopenharmony_ci    SkASSERT((src[0].dimensions() == this->dimensions() && pt.isZero()) || numLevels == 1);
331cb93a386Sopenharmony_ci    SkASSERT(numLevels == 1 ||
332cb93a386Sopenharmony_ci             (this->asTextureProxy() && this->asTextureProxy()->mipmapped() == GrMipmapped::kYes));
333cb93a386Sopenharmony_ci    // Our public caller should have clipped to the bounds of the surface already.
334cb93a386Sopenharmony_ci    SkASSERT(SkIRect::MakeSize(this->dimensions()).contains(
335cb93a386Sopenharmony_ci            SkIRect::MakePtSize(pt, src[0].dimensions())));
336cb93a386Sopenharmony_ci
337cb93a386Sopenharmony_ci    if (!dContext) {
338cb93a386Sopenharmony_ci        return false;
339cb93a386Sopenharmony_ci    }
340cb93a386Sopenharmony_ci
341cb93a386Sopenharmony_ci    if (this->asSurfaceProxy()->readOnly()) {
342cb93a386Sopenharmony_ci        return false;
343cb93a386Sopenharmony_ci    }
344cb93a386Sopenharmony_ci
345cb93a386Sopenharmony_ci    if (src[0].colorType() == GrColorType::kUnknown) {
346cb93a386Sopenharmony_ci        return false;
347cb93a386Sopenharmony_ci    }
348cb93a386Sopenharmony_ci
349cb93a386Sopenharmony_ci    if (!alpha_types_compatible(src[0].alphaType(), this->colorInfo().alphaType())) {
350cb93a386Sopenharmony_ci        return false;
351cb93a386Sopenharmony_ci    }
352cb93a386Sopenharmony_ci
353cb93a386Sopenharmony_ci    GrSurfaceProxy* dstProxy = this->asSurfaceProxy();
354cb93a386Sopenharmony_ci
355cb93a386Sopenharmony_ci    if (dstProxy->framebufferOnly()) {
356cb93a386Sopenharmony_ci        return false;
357cb93a386Sopenharmony_ci    }
358cb93a386Sopenharmony_ci
359cb93a386Sopenharmony_ci    if (!dstProxy->instantiate(dContext->priv().resourceProvider())) {
360cb93a386Sopenharmony_ci        return false;
361cb93a386Sopenharmony_ci    }
362cb93a386Sopenharmony_ci
363cb93a386Sopenharmony_ci    GrSurface* dstSurface = dstProxy->peekSurface();
364cb93a386Sopenharmony_ci
365cb93a386Sopenharmony_ci    SkColorSpaceXformSteps::Flags flags =
366cb93a386Sopenharmony_ci            SkColorSpaceXformSteps{src[0].colorInfo(), this->colorInfo()}.flags;
367cb93a386Sopenharmony_ci    bool unpremul            = flags.unpremul,
368cb93a386Sopenharmony_ci         needColorConversion = flags.linearize || flags.gamut_transform || flags.encode,
369cb93a386Sopenharmony_ci         premul              = flags.premul;
370cb93a386Sopenharmony_ci
371cb93a386Sopenharmony_ci    const GrCaps* caps = dContext->priv().caps();
372cb93a386Sopenharmony_ci
373cb93a386Sopenharmony_ci    auto rgbaDefaultFormat = caps->getDefaultBackendFormat(GrColorType::kRGBA_8888,
374cb93a386Sopenharmony_ci                                                           GrRenderable::kNo);
375cb93a386Sopenharmony_ci
376cb93a386Sopenharmony_ci    GrColorType dstColorType = this->colorInfo().colorType();
377cb93a386Sopenharmony_ci    // For canvas2D putImageData performance we have a special code path for unpremul RGBA_8888 srcs
378cb93a386Sopenharmony_ci    // that are premultiplied on the GPU. This is kept as narrow as possible for now.
379cb93a386Sopenharmony_ci    bool canvas2DFastPath = !caps->avoidWritePixelsFastPath() && premul && !needColorConversion &&
380cb93a386Sopenharmony_ci                            (src[0].colorType() == GrColorType::kRGBA_8888 ||
381cb93a386Sopenharmony_ci                             src[0].colorType() == GrColorType::kBGRA_8888) &&
382cb93a386Sopenharmony_ci                            this->asFillContext() &&
383cb93a386Sopenharmony_ci                            (dstColorType == GrColorType::kRGBA_8888 ||
384cb93a386Sopenharmony_ci                             dstColorType == GrColorType::kBGRA_8888) &&
385cb93a386Sopenharmony_ci                            rgbaDefaultFormat.isValid() &&
386cb93a386Sopenharmony_ci                            dContext->priv().validPMUPMConversionExists();
387cb93a386Sopenharmony_ci
388cb93a386Sopenharmony_ci    // Since the validPMUPMConversionExists function actually submits work to the gpu to do its
389cb93a386Sopenharmony_ci    // tests, it is possible that during that call we have abanoned the context. Thus we do an
390cb93a386Sopenharmony_ci    // abanoned check here to make sure we are still valid.
391cb93a386Sopenharmony_ci    RETURN_FALSE_IF_ABANDONED
392cb93a386Sopenharmony_ci
393cb93a386Sopenharmony_ci    // Drawing code path doesn't support writing to levels and doesn't support inserting layout
394cb93a386Sopenharmony_ci    // transitions.
395cb93a386Sopenharmony_ci    if ((!caps->surfaceSupportsWritePixels(dstSurface) || canvas2DFastPath) && numLevels == 1) {
396cb93a386Sopenharmony_ci        GrColorInfo tempColorInfo;
397cb93a386Sopenharmony_ci        GrBackendFormat format;
398cb93a386Sopenharmony_ci        GrSwizzle tempReadSwizzle;
399cb93a386Sopenharmony_ci        if (canvas2DFastPath) {
400cb93a386Sopenharmony_ci            tempColorInfo = {GrColorType::kRGBA_8888,
401cb93a386Sopenharmony_ci                             kUnpremul_SkAlphaType,
402cb93a386Sopenharmony_ci                             this->colorInfo().refColorSpace()};
403cb93a386Sopenharmony_ci            format = rgbaDefaultFormat;
404cb93a386Sopenharmony_ci        } else {
405cb93a386Sopenharmony_ci            tempColorInfo = this->colorInfo();
406cb93a386Sopenharmony_ci            format = dstProxy->backendFormat().makeTexture2D();
407cb93a386Sopenharmony_ci            if (!format.isValid()) {
408cb93a386Sopenharmony_ci                return false;
409cb93a386Sopenharmony_ci            }
410cb93a386Sopenharmony_ci            tempReadSwizzle = this->readSwizzle();
411cb93a386Sopenharmony_ci        }
412cb93a386Sopenharmony_ci
413cb93a386Sopenharmony_ci        // It is more efficient for us to write pixels into a top left origin so we prefer that.
414cb93a386Sopenharmony_ci        // However, if the final proxy isn't a render target then we must use a copy to move the
415cb93a386Sopenharmony_ci        // data into it which requires the origins to match. If the final proxy is a render target
416cb93a386Sopenharmony_ci        // we can use a draw instead which doesn't have this origin restriction. Thus for render
417cb93a386Sopenharmony_ci        // targets we will use top left and otherwise we will make the origins match.
418cb93a386Sopenharmony_ci        GrSurfaceOrigin tempOrigin =
419cb93a386Sopenharmony_ci                this->asFillContext() ? kTopLeft_GrSurfaceOrigin : this->origin();
420cb93a386Sopenharmony_ci        auto tempProxy = dContext->priv().proxyProvider()->createProxy(format,
421cb93a386Sopenharmony_ci                                                                       src[0].dimensions(),
422cb93a386Sopenharmony_ci                                                                       GrRenderable::kNo,
423cb93a386Sopenharmony_ci                                                                       1,
424cb93a386Sopenharmony_ci                                                                       GrMipmapped::kNo,
425cb93a386Sopenharmony_ci                                                                       SkBackingFit::kApprox,
426cb93a386Sopenharmony_ci                                                                       SkBudgeted::kYes,
427cb93a386Sopenharmony_ci                                                                       GrProtected::kNo);
428cb93a386Sopenharmony_ci        if (!tempProxy) {
429cb93a386Sopenharmony_ci            return false;
430cb93a386Sopenharmony_ci        }
431cb93a386Sopenharmony_ci        GrSurfaceProxyView tempView(tempProxy, tempOrigin, tempReadSwizzle);
432cb93a386Sopenharmony_ci        SurfaceContext tempCtx(dContext, tempView, tempColorInfo);
433cb93a386Sopenharmony_ci
434cb93a386Sopenharmony_ci        // In the fast path we always write the srcData to the temp context as though it were RGBA.
435cb93a386Sopenharmony_ci        // When the data is really BGRA the write will cause the R and B channels to be swapped in
436cb93a386Sopenharmony_ci        // the intermediate surface which gets corrected by a swizzle effect when drawing to the
437cb93a386Sopenharmony_ci        // dst.
438cb93a386Sopenharmony_ci        GrCPixmap origSrcBase = src[0];
439cb93a386Sopenharmony_ci        GrCPixmap srcBase = origSrcBase;
440cb93a386Sopenharmony_ci        if (canvas2DFastPath) {
441cb93a386Sopenharmony_ci            srcBase = GrCPixmap(origSrcBase.info().makeColorType(GrColorType::kRGBA_8888),
442cb93a386Sopenharmony_ci                                origSrcBase.addr(),
443cb93a386Sopenharmony_ci                                origSrcBase.rowBytes());
444cb93a386Sopenharmony_ci        }
445cb93a386Sopenharmony_ci        if (!tempCtx.writePixels(dContext, srcBase, {0, 0})) {
446cb93a386Sopenharmony_ci            return false;
447cb93a386Sopenharmony_ci        }
448cb93a386Sopenharmony_ci
449cb93a386Sopenharmony_ci        if (this->asFillContext()) {
450cb93a386Sopenharmony_ci            std::unique_ptr<GrFragmentProcessor> fp;
451cb93a386Sopenharmony_ci            if (canvas2DFastPath) {
452cb93a386Sopenharmony_ci                fp = dContext->priv().createUPMToPMEffect(
453cb93a386Sopenharmony_ci                        GrTextureEffect::Make(std::move(tempView), tempColorInfo.alphaType()));
454cb93a386Sopenharmony_ci                // Important: check the original src color type here!
455cb93a386Sopenharmony_ci                if (origSrcBase.colorType() == GrColorType::kBGRA_8888) {
456cb93a386Sopenharmony_ci                    fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
457cb93a386Sopenharmony_ci                }
458cb93a386Sopenharmony_ci            } else {
459cb93a386Sopenharmony_ci                fp = GrTextureEffect::Make(std::move(tempView), tempColorInfo.alphaType());
460cb93a386Sopenharmony_ci            }
461cb93a386Sopenharmony_ci            if (!fp) {
462cb93a386Sopenharmony_ci                return false;
463cb93a386Sopenharmony_ci            }
464cb93a386Sopenharmony_ci            this->asFillContext()->fillRectToRectWithFP(
465cb93a386Sopenharmony_ci                    SkIRect::MakeSize(srcBase.dimensions()),
466cb93a386Sopenharmony_ci                    SkIRect::MakePtSize(pt, srcBase.dimensions()),
467cb93a386Sopenharmony_ci                    std::move(fp));
468cb93a386Sopenharmony_ci        } else {
469cb93a386Sopenharmony_ci            SkIRect srcRect = SkIRect::MakeSize(srcBase.dimensions());
470cb93a386Sopenharmony_ci            SkIPoint dstPoint = SkIPoint::Make(pt.fX, pt.fY);
471cb93a386Sopenharmony_ci            if (!this->copy(std::move(tempProxy), srcRect, dstPoint)) {
472cb93a386Sopenharmony_ci                return false;
473cb93a386Sopenharmony_ci            }
474cb93a386Sopenharmony_ci        }
475cb93a386Sopenharmony_ci        return true;
476cb93a386Sopenharmony_ci    }
477cb93a386Sopenharmony_ci
478cb93a386Sopenharmony_ci    GrColorType srcColorType = src[0].colorType();
479cb93a386Sopenharmony_ci    auto [allowedColorType, _] =
480cb93a386Sopenharmony_ci            caps->supportedWritePixelsColorType(this->colorInfo().colorType(),
481cb93a386Sopenharmony_ci                                                dstProxy->backendFormat(),
482cb93a386Sopenharmony_ci                                                srcColorType);
483cb93a386Sopenharmony_ci    bool flip = this->origin() == kBottomLeft_GrSurfaceOrigin;
484cb93a386Sopenharmony_ci
485cb93a386Sopenharmony_ci    bool convertAll = premul              ||
486cb93a386Sopenharmony_ci                      unpremul            ||
487cb93a386Sopenharmony_ci                      needColorConversion ||
488cb93a386Sopenharmony_ci                      flip                ||
489cb93a386Sopenharmony_ci                      (srcColorType != allowedColorType);
490cb93a386Sopenharmony_ci    bool mustBeTight = !caps->writePixelsRowBytesSupport();
491cb93a386Sopenharmony_ci    size_t tmpSize = 0;
492cb93a386Sopenharmony_ci    if (mustBeTight || convertAll) {
493cb93a386Sopenharmony_ci        for (int i = 0; i < numLevels; ++i) {
494cb93a386Sopenharmony_ci            if (convertAll || (mustBeTight && src[i].rowBytes() != src[i].info().minRowBytes())) {
495cb93a386Sopenharmony_ci                tmpSize += src[i].info().makeColorType(allowedColorType).minRowBytes()*
496cb93a386Sopenharmony_ci                           src[i].height();
497cb93a386Sopenharmony_ci            }
498cb93a386Sopenharmony_ci        }
499cb93a386Sopenharmony_ci    }
500cb93a386Sopenharmony_ci
501cb93a386Sopenharmony_ci    auto tmpData = tmpSize ? SkData::MakeUninitialized(tmpSize) : nullptr;
502cb93a386Sopenharmony_ci    void*    tmp = tmpSize ? tmpData->writable_data()           : nullptr;
503cb93a386Sopenharmony_ci    SkAutoSTArray<15, GrMipLevel> srcLevels(numLevels);
504cb93a386Sopenharmony_ci    bool ownAllStorage = true;
505cb93a386Sopenharmony_ci    for (int i = 0; i < numLevels; ++i) {
506cb93a386Sopenharmony_ci        if (convertAll || (mustBeTight && src[i].rowBytes() != src[i].info().minRowBytes())) {
507cb93a386Sopenharmony_ci            GrImageInfo tmpInfo(allowedColorType,
508cb93a386Sopenharmony_ci                                this->colorInfo().alphaType(),
509cb93a386Sopenharmony_ci                                this->colorInfo().refColorSpace(),
510cb93a386Sopenharmony_ci                                src[i].dimensions());
511cb93a386Sopenharmony_ci            auto tmpRB = tmpInfo.minRowBytes();
512cb93a386Sopenharmony_ci            GrPixmap tmpPM(tmpInfo, tmp, tmpRB);
513cb93a386Sopenharmony_ci            SkAssertResult(GrConvertPixels(tmpPM, src[i], flip));
514cb93a386Sopenharmony_ci            srcLevels[i] = {tmpPM.addr(), tmpPM.rowBytes(), tmpData};
515cb93a386Sopenharmony_ci            tmp = SkTAddOffset<void>(tmp, tmpRB*tmpPM.height());
516cb93a386Sopenharmony_ci        } else {
517cb93a386Sopenharmony_ci            srcLevels[i] = {src[i].addr(), src[i].rowBytes(), src[i].pixelStorage()};
518cb93a386Sopenharmony_ci            ownAllStorage &= src[i].ownsPixels();
519cb93a386Sopenharmony_ci        }
520cb93a386Sopenharmony_ci    }
521cb93a386Sopenharmony_ci    pt.fY = flip ? dstSurface->height() - pt.fY - src[0].height() : pt.fY;
522cb93a386Sopenharmony_ci
523cb93a386Sopenharmony_ci    if (!dContext->priv().drawingManager()->newWritePixelsTask(
524cb93a386Sopenharmony_ci                sk_ref_sp(dstProxy),
525cb93a386Sopenharmony_ci                SkIRect::MakePtSize(pt, src[0].dimensions()),
526cb93a386Sopenharmony_ci                allowedColorType,
527cb93a386Sopenharmony_ci                this->colorInfo().colorType(),
528cb93a386Sopenharmony_ci                srcLevels.begin(),
529cb93a386Sopenharmony_ci                numLevels)) {
530cb93a386Sopenharmony_ci        return false;
531cb93a386Sopenharmony_ci    }
532cb93a386Sopenharmony_ci    if (numLevels > 1) {
533cb93a386Sopenharmony_ci        dstProxy->asTextureProxy()->markMipmapsClean();
534cb93a386Sopenharmony_ci    }
535cb93a386Sopenharmony_ci    if (!ownAllStorage) {
536cb93a386Sopenharmony_ci        // If any pixmap doesn't own its pixels then we must flush so that the pixels are pushed to
537cb93a386Sopenharmony_ci        // the GPU before we return.
538cb93a386Sopenharmony_ci        dContext->priv().flushSurface(dstProxy);
539cb93a386Sopenharmony_ci    }
540cb93a386Sopenharmony_ci    return true;
541cb93a386Sopenharmony_ci}
542cb93a386Sopenharmony_ci
543cb93a386Sopenharmony_civoid SurfaceContext::asyncRescaleAndReadPixels(GrDirectContext* dContext,
544cb93a386Sopenharmony_ci                                               const SkImageInfo& info,
545cb93a386Sopenharmony_ci                                               const SkIRect& srcRect,
546cb93a386Sopenharmony_ci                                               RescaleGamma rescaleGamma,
547cb93a386Sopenharmony_ci                                               RescaleMode rescaleMode,
548cb93a386Sopenharmony_ci                                               ReadPixelsCallback callback,
549cb93a386Sopenharmony_ci                                               ReadPixelsContext callbackContext) {
550cb93a386Sopenharmony_ci    if (!dContext) {
551cb93a386Sopenharmony_ci        callback(callbackContext, nullptr);
552cb93a386Sopenharmony_ci        return;
553cb93a386Sopenharmony_ci    }
554cb93a386Sopenharmony_ci    auto rt = this->asRenderTargetProxy();
555cb93a386Sopenharmony_ci    if (rt && rt->wrapsVkSecondaryCB()) {
556cb93a386Sopenharmony_ci        callback(callbackContext, nullptr);
557cb93a386Sopenharmony_ci        return;
558cb93a386Sopenharmony_ci    }
559cb93a386Sopenharmony_ci    if (rt && rt->framebufferOnly()) {
560cb93a386Sopenharmony_ci        callback(callbackContext, nullptr);
561cb93a386Sopenharmony_ci        return;
562cb93a386Sopenharmony_ci    }
563cb93a386Sopenharmony_ci    auto dstCT = SkColorTypeToGrColorType(info.colorType());
564cb93a386Sopenharmony_ci    if (dstCT == GrColorType::kUnknown) {
565cb93a386Sopenharmony_ci        callback(callbackContext, nullptr);
566cb93a386Sopenharmony_ci        return;
567cb93a386Sopenharmony_ci    }
568cb93a386Sopenharmony_ci    bool needsRescale = srcRect.size() != info.dimensions()               ||
569cb93a386Sopenharmony_ci                        this->origin() == kBottomLeft_GrSurfaceOrigin     ||
570cb93a386Sopenharmony_ci                        this->colorInfo().alphaType() != info.alphaType() ||
571cb93a386Sopenharmony_ci                        !SkColorSpace::Equals(this->colorInfo().colorSpace(), info.colorSpace());
572cb93a386Sopenharmony_ci    auto colorTypeOfFinalContext = this->colorInfo().colorType();
573cb93a386Sopenharmony_ci    auto backendFormatOfFinalContext = this->asSurfaceProxy()->backendFormat();
574cb93a386Sopenharmony_ci    if (needsRescale) {
575cb93a386Sopenharmony_ci        colorTypeOfFinalContext = dstCT;
576cb93a386Sopenharmony_ci        backendFormatOfFinalContext =
577cb93a386Sopenharmony_ci                this->caps()->getDefaultBackendFormat(dstCT, GrRenderable::kYes);
578cb93a386Sopenharmony_ci    }
579cb93a386Sopenharmony_ci    auto readInfo = this->caps()->supportedReadPixelsColorType(colorTypeOfFinalContext,
580cb93a386Sopenharmony_ci                                                               backendFormatOfFinalContext,
581cb93a386Sopenharmony_ci                                                               dstCT);
582cb93a386Sopenharmony_ci    // Fail if we can't read from the source surface's color type.
583cb93a386Sopenharmony_ci    if (readInfo.fColorType == GrColorType::kUnknown) {
584cb93a386Sopenharmony_ci        callback(callbackContext, nullptr);
585cb93a386Sopenharmony_ci        return;
586cb93a386Sopenharmony_ci    }
587cb93a386Sopenharmony_ci    // Fail if read color type does not have all of dstCT's color channels and those missing color
588cb93a386Sopenharmony_ci    // channels are in the src.
589cb93a386Sopenharmony_ci    uint32_t dstChannels = GrColorTypeChannelFlags(dstCT);
590cb93a386Sopenharmony_ci    uint32_t legalReadChannels = GrColorTypeChannelFlags(readInfo.fColorType);
591cb93a386Sopenharmony_ci    uint32_t srcChannels = GrColorTypeChannelFlags(this->colorInfo().colorType());
592cb93a386Sopenharmony_ci    if ((~legalReadChannels & dstChannels) & srcChannels) {
593cb93a386Sopenharmony_ci        callback(callbackContext, nullptr);
594cb93a386Sopenharmony_ci        return;
595cb93a386Sopenharmony_ci    }
596cb93a386Sopenharmony_ci
597cb93a386Sopenharmony_ci    std::unique_ptr<skgpu::SurfaceFillContext> tempFC;
598cb93a386Sopenharmony_ci    int x = srcRect.fLeft;
599cb93a386Sopenharmony_ci    int y = srcRect.fTop;
600cb93a386Sopenharmony_ci    if (needsRescale) {
601cb93a386Sopenharmony_ci        tempFC = this->rescale(info, kTopLeft_GrSurfaceOrigin, srcRect, rescaleGamma, rescaleMode);
602cb93a386Sopenharmony_ci        if (!tempFC) {
603cb93a386Sopenharmony_ci            callback(callbackContext, nullptr);
604cb93a386Sopenharmony_ci            return;
605cb93a386Sopenharmony_ci        }
606cb93a386Sopenharmony_ci        SkASSERT(SkColorSpace::Equals(tempFC->colorInfo().colorSpace(), info.colorSpace()));
607cb93a386Sopenharmony_ci        SkASSERT(tempFC->origin() == kTopLeft_GrSurfaceOrigin);
608cb93a386Sopenharmony_ci        x = y = 0;
609cb93a386Sopenharmony_ci    }
610cb93a386Sopenharmony_ci    auto srcCtx = tempFC ? tempFC.get() : this;
611cb93a386Sopenharmony_ci    return srcCtx->asyncReadPixels(dContext,
612cb93a386Sopenharmony_ci                                   SkIRect::MakePtSize({x, y}, info.dimensions()),
613cb93a386Sopenharmony_ci                                   info.colorType(),
614cb93a386Sopenharmony_ci                                   callback,
615cb93a386Sopenharmony_ci                                   callbackContext);
616cb93a386Sopenharmony_ci}
617cb93a386Sopenharmony_ci
618cb93a386Sopenharmony_ciclass SurfaceContext::AsyncReadResult : public SkImage::AsyncReadResult {
619cb93a386Sopenharmony_cipublic:
620cb93a386Sopenharmony_ci    AsyncReadResult(GrDirectContext::DirectContextID intendedRecipient)
621cb93a386Sopenharmony_ci        : fIntendedRecipient(intendedRecipient) {
622cb93a386Sopenharmony_ci    }
623cb93a386Sopenharmony_ci
624cb93a386Sopenharmony_ci    ~AsyncReadResult() override {
625cb93a386Sopenharmony_ci        for (int i = 0; i < fPlanes.count(); ++i) {
626cb93a386Sopenharmony_ci            fPlanes[i].releaseMappedBuffer(fIntendedRecipient);
627cb93a386Sopenharmony_ci        }
628cb93a386Sopenharmony_ci    }
629cb93a386Sopenharmony_ci
630cb93a386Sopenharmony_ci    int count() const override { return fPlanes.count(); }
631cb93a386Sopenharmony_ci    const void* data(int i) const override { return fPlanes[i].data(); }
632cb93a386Sopenharmony_ci    size_t rowBytes(int i) const override { return fPlanes[i].rowBytes(); }
633cb93a386Sopenharmony_ci
634cb93a386Sopenharmony_ci    bool addTransferResult(const PixelTransferResult& result,
635cb93a386Sopenharmony_ci                           SkISize dimensions,
636cb93a386Sopenharmony_ci                           size_t rowBytes,
637cb93a386Sopenharmony_ci                           GrClientMappedBufferManager* manager) {
638cb93a386Sopenharmony_ci        SkASSERT(!result.fTransferBuffer->isMapped());
639cb93a386Sopenharmony_ci        const void* mappedData = result.fTransferBuffer->map();
640cb93a386Sopenharmony_ci        if (!mappedData) {
641cb93a386Sopenharmony_ci            return false;
642cb93a386Sopenharmony_ci        }
643cb93a386Sopenharmony_ci        if (result.fPixelConverter) {
644cb93a386Sopenharmony_ci            size_t size = rowBytes*dimensions.height();
645cb93a386Sopenharmony_ci            sk_sp<SkData> data = SkData::MakeUninitialized(size);
646cb93a386Sopenharmony_ci            result.fPixelConverter(data->writable_data(), mappedData);
647cb93a386Sopenharmony_ci            this->addCpuPlane(std::move(data), rowBytes);
648cb93a386Sopenharmony_ci            result.fTransferBuffer->unmap();
649cb93a386Sopenharmony_ci        } else {
650cb93a386Sopenharmony_ci            manager->insert(result.fTransferBuffer);
651cb93a386Sopenharmony_ci            this->addMappedPlane(mappedData, rowBytes, std::move(result.fTransferBuffer));
652cb93a386Sopenharmony_ci        }
653cb93a386Sopenharmony_ci        return true;
654cb93a386Sopenharmony_ci    }
655cb93a386Sopenharmony_ci
656cb93a386Sopenharmony_ci    void addCpuPlane(sk_sp<SkData> data, size_t rowBytes) {
657cb93a386Sopenharmony_ci        SkASSERT(data);
658cb93a386Sopenharmony_ci        SkASSERT(rowBytes > 0);
659cb93a386Sopenharmony_ci        fPlanes.emplace_back(std::move(data), rowBytes);
660cb93a386Sopenharmony_ci    }
661cb93a386Sopenharmony_ci
662cb93a386Sopenharmony_ciprivate:
663cb93a386Sopenharmony_ci    void addMappedPlane(const void* data, size_t rowBytes, sk_sp<GrGpuBuffer> mappedBuffer) {
664cb93a386Sopenharmony_ci        SkASSERT(data);
665cb93a386Sopenharmony_ci        SkASSERT(rowBytes > 0);
666cb93a386Sopenharmony_ci        SkASSERT(mappedBuffer);
667cb93a386Sopenharmony_ci        SkASSERT(mappedBuffer->isMapped());
668cb93a386Sopenharmony_ci        fPlanes.emplace_back(std::move(mappedBuffer), rowBytes);
669cb93a386Sopenharmony_ci    }
670cb93a386Sopenharmony_ci
671cb93a386Sopenharmony_ci    class Plane {
672cb93a386Sopenharmony_ci    public:
673cb93a386Sopenharmony_ci        Plane(sk_sp<GrGpuBuffer> buffer, size_t rowBytes)
674cb93a386Sopenharmony_ci                : fMappedBuffer(std::move(buffer)), fRowBytes(rowBytes) {}
675cb93a386Sopenharmony_ci        Plane(sk_sp<SkData> data, size_t rowBytes) : fData(std::move(data)), fRowBytes(rowBytes) {}
676cb93a386Sopenharmony_ci
677cb93a386Sopenharmony_ci        Plane(const Plane&) = delete;
678cb93a386Sopenharmony_ci        Plane(Plane&&) = default;
679cb93a386Sopenharmony_ci
680cb93a386Sopenharmony_ci        ~Plane() { SkASSERT(!fMappedBuffer); }
681cb93a386Sopenharmony_ci
682cb93a386Sopenharmony_ci        Plane& operator=(const Plane&) = delete;
683cb93a386Sopenharmony_ci        Plane& operator=(Plane&&) = default;
684cb93a386Sopenharmony_ci
685cb93a386Sopenharmony_ci        void releaseMappedBuffer(GrDirectContext::DirectContextID intendedRecipient) {
686cb93a386Sopenharmony_ci            if (fMappedBuffer) {
687cb93a386Sopenharmony_ci                GrClientMappedBufferManager::BufferFinishedMessageBus::Post(
688cb93a386Sopenharmony_ci                        {std::move(fMappedBuffer), intendedRecipient});
689cb93a386Sopenharmony_ci            }
690cb93a386Sopenharmony_ci        }
691cb93a386Sopenharmony_ci
692cb93a386Sopenharmony_ci        const void* data() const {
693cb93a386Sopenharmony_ci            if (fMappedBuffer) {
694cb93a386Sopenharmony_ci                SkASSERT(!fData);
695cb93a386Sopenharmony_ci                SkASSERT(fMappedBuffer->isMapped());
696cb93a386Sopenharmony_ci                return fMappedBuffer->map();
697cb93a386Sopenharmony_ci            }
698cb93a386Sopenharmony_ci            SkASSERT(fData);
699cb93a386Sopenharmony_ci            return fData->data();
700cb93a386Sopenharmony_ci        }
701cb93a386Sopenharmony_ci
702cb93a386Sopenharmony_ci        size_t rowBytes() const { return fRowBytes; }
703cb93a386Sopenharmony_ci
704cb93a386Sopenharmony_ci    private:
705cb93a386Sopenharmony_ci        sk_sp<SkData> fData;
706cb93a386Sopenharmony_ci        sk_sp<GrGpuBuffer> fMappedBuffer;
707cb93a386Sopenharmony_ci        size_t fRowBytes;
708cb93a386Sopenharmony_ci    };
709cb93a386Sopenharmony_ci    SkSTArray<3, Plane> fPlanes;
710cb93a386Sopenharmony_ci    GrDirectContext::DirectContextID fIntendedRecipient;
711cb93a386Sopenharmony_ci};
712cb93a386Sopenharmony_ci
713cb93a386Sopenharmony_civoid SurfaceContext::asyncReadPixels(GrDirectContext* dContext,
714cb93a386Sopenharmony_ci                                     const SkIRect& rect,
715cb93a386Sopenharmony_ci                                     SkColorType colorType,
716cb93a386Sopenharmony_ci                                     ReadPixelsCallback callback,
717cb93a386Sopenharmony_ci                                     ReadPixelsContext callbackContext) {
718cb93a386Sopenharmony_ci    SkASSERT(rect.fLeft >= 0 && rect.fRight <= this->width());
719cb93a386Sopenharmony_ci    SkASSERT(rect.fTop >= 0 && rect.fBottom <= this->height());
720cb93a386Sopenharmony_ci
721cb93a386Sopenharmony_ci    if (!dContext || this->asSurfaceProxy()->isProtected() == GrProtected::kYes) {
722cb93a386Sopenharmony_ci        callback(callbackContext, nullptr);
723cb93a386Sopenharmony_ci        return;
724cb93a386Sopenharmony_ci    }
725cb93a386Sopenharmony_ci
726cb93a386Sopenharmony_ci    auto mappedBufferManager = dContext->priv().clientMappedBufferManager();
727cb93a386Sopenharmony_ci
728cb93a386Sopenharmony_ci    auto transferResult = this->transferPixels(SkColorTypeToGrColorType(colorType), rect);
729cb93a386Sopenharmony_ci
730cb93a386Sopenharmony_ci    if (!transferResult.fTransferBuffer) {
731cb93a386Sopenharmony_ci        auto ii = SkImageInfo::Make(rect.size(), colorType, this->colorInfo().alphaType(),
732cb93a386Sopenharmony_ci                                    this->colorInfo().refColorSpace());
733cb93a386Sopenharmony_ci        static const GrDirectContext::DirectContextID kInvalid;
734cb93a386Sopenharmony_ci        auto result = std::make_unique<AsyncReadResult>(kInvalid);
735cb93a386Sopenharmony_ci        GrPixmap pm = GrPixmap::Allocate(ii);
736cb93a386Sopenharmony_ci        result->addCpuPlane(pm.pixelStorage(), pm.rowBytes());
737cb93a386Sopenharmony_ci
738cb93a386Sopenharmony_ci        SkIPoint pt{rect.fLeft, rect.fTop};
739cb93a386Sopenharmony_ci        if (!this->readPixels(dContext, pm, pt)) {
740cb93a386Sopenharmony_ci            callback(callbackContext, nullptr);
741cb93a386Sopenharmony_ci            return;
742cb93a386Sopenharmony_ci        }
743cb93a386Sopenharmony_ci        callback(callbackContext, std::move(result));
744cb93a386Sopenharmony_ci        return;
745cb93a386Sopenharmony_ci    }
746cb93a386Sopenharmony_ci
747cb93a386Sopenharmony_ci    struct FinishContext {
748cb93a386Sopenharmony_ci        ReadPixelsCallback* fClientCallback;
749cb93a386Sopenharmony_ci        ReadPixelsContext fClientContext;
750cb93a386Sopenharmony_ci        SkISize fSize;
751cb93a386Sopenharmony_ci        SkColorType fColorType;
752cb93a386Sopenharmony_ci        size_t fBufferAlignment;
753cb93a386Sopenharmony_ci        GrClientMappedBufferManager* fMappedBufferManager;
754cb93a386Sopenharmony_ci        PixelTransferResult fTransferResult;
755cb93a386Sopenharmony_ci    };
756cb93a386Sopenharmony_ci    // Assumption is that the caller would like to flush. We could take a parameter or require an
757cb93a386Sopenharmony_ci    // explicit flush from the caller. We'd have to have a way to defer attaching the finish
758cb93a386Sopenharmony_ci    // callback to GrGpu until after the next flush that flushes our op list, though.
759cb93a386Sopenharmony_ci    auto* finishContext = new FinishContext{callback,
760cb93a386Sopenharmony_ci                                            callbackContext,
761cb93a386Sopenharmony_ci                                            rect.size(),
762cb93a386Sopenharmony_ci                                            colorType,
763cb93a386Sopenharmony_ci                                            this->caps()->transferBufferAlignment(),
764cb93a386Sopenharmony_ci                                            mappedBufferManager,
765cb93a386Sopenharmony_ci                                            std::move(transferResult)};
766cb93a386Sopenharmony_ci    auto finishCallback = [](GrGpuFinishedContext c) {
767cb93a386Sopenharmony_ci        const auto* context = reinterpret_cast<const FinishContext*>(c);
768cb93a386Sopenharmony_ci        auto manager = context->fMappedBufferManager;
769cb93a386Sopenharmony_ci        auto result = std::make_unique<AsyncReadResult>(manager->owningDirectContext());
770cb93a386Sopenharmony_ci        size_t rowBytes =
771cb93a386Sopenharmony_ci                SkAlignTo(context->fSize.width() * SkColorTypeBytesPerPixel(context->fColorType),
772cb93a386Sopenharmony_ci                          context->fBufferAlignment);
773cb93a386Sopenharmony_ci        if (!result->addTransferResult(context->fTransferResult, context->fSize, rowBytes,
774cb93a386Sopenharmony_ci                                       manager)) {
775cb93a386Sopenharmony_ci            result.reset();
776cb93a386Sopenharmony_ci        }
777cb93a386Sopenharmony_ci        (*context->fClientCallback)(context->fClientContext, std::move(result));
778cb93a386Sopenharmony_ci        delete context;
779cb93a386Sopenharmony_ci    };
780cb93a386Sopenharmony_ci    GrFlushInfo flushInfo;
781cb93a386Sopenharmony_ci    flushInfo.fFinishedContext = finishContext;
782cb93a386Sopenharmony_ci    flushInfo.fFinishedProc = finishCallback;
783cb93a386Sopenharmony_ci
784cb93a386Sopenharmony_ci    dContext->priv().flushSurface(this->asSurfaceProxy(),
785cb93a386Sopenharmony_ci                                  SkSurface::BackendSurfaceAccess::kNoAccess,
786cb93a386Sopenharmony_ci                                  flushInfo);
787cb93a386Sopenharmony_ci}
788cb93a386Sopenharmony_ci
789cb93a386Sopenharmony_civoid SurfaceContext::asyncRescaleAndReadPixelsYUV420(GrDirectContext* dContext,
790cb93a386Sopenharmony_ci                                                     SkYUVColorSpace yuvColorSpace,
791cb93a386Sopenharmony_ci                                                     sk_sp<SkColorSpace> dstColorSpace,
792cb93a386Sopenharmony_ci                                                     const SkIRect& srcRect,
793cb93a386Sopenharmony_ci                                                     SkISize dstSize,
794cb93a386Sopenharmony_ci                                                     RescaleGamma rescaleGamma,
795cb93a386Sopenharmony_ci                                                     RescaleMode rescaleMode,
796cb93a386Sopenharmony_ci                                                     ReadPixelsCallback callback,
797cb93a386Sopenharmony_ci                                                     ReadPixelsContext callbackContext) {
798cb93a386Sopenharmony_ci    SkASSERT(srcRect.fLeft >= 0 && srcRect.fRight <= this->width());
799cb93a386Sopenharmony_ci    SkASSERT(srcRect.fTop >= 0 && srcRect.fBottom <= this->height());
800cb93a386Sopenharmony_ci    SkASSERT(!dstSize.isZero());
801cb93a386Sopenharmony_ci    SkASSERT((dstSize.width() % 2 == 0) && (dstSize.height() % 2 == 0));
802cb93a386Sopenharmony_ci
803cb93a386Sopenharmony_ci    if (!dContext) {
804cb93a386Sopenharmony_ci        callback(callbackContext, nullptr);
805cb93a386Sopenharmony_ci        return;
806cb93a386Sopenharmony_ci    }
807cb93a386Sopenharmony_ci    auto rt = this->asRenderTargetProxy();
808cb93a386Sopenharmony_ci    if (rt && rt->wrapsVkSecondaryCB()) {
809cb93a386Sopenharmony_ci        callback(callbackContext, nullptr);
810cb93a386Sopenharmony_ci        return;
811cb93a386Sopenharmony_ci    }
812cb93a386Sopenharmony_ci    if (rt && rt->framebufferOnly()) {
813cb93a386Sopenharmony_ci        callback(callbackContext, nullptr);
814cb93a386Sopenharmony_ci        return;
815cb93a386Sopenharmony_ci    }
816cb93a386Sopenharmony_ci    if (this->asSurfaceProxy()->isProtected() == GrProtected::kYes) {
817cb93a386Sopenharmony_ci        callback(callbackContext, nullptr);
818cb93a386Sopenharmony_ci        return;
819cb93a386Sopenharmony_ci    }
820cb93a386Sopenharmony_ci    int x = srcRect.fLeft;
821cb93a386Sopenharmony_ci    int y = srcRect.fTop;
822cb93a386Sopenharmony_ci    bool needsRescale = srcRect.size() != dstSize ||
823cb93a386Sopenharmony_ci                        !SkColorSpace::Equals(this->colorInfo().colorSpace(), dstColorSpace.get());
824cb93a386Sopenharmony_ci    GrSurfaceProxyView srcView = this->readSurfaceView();
825cb93a386Sopenharmony_ci    if (needsRescale) {
826cb93a386Sopenharmony_ci        auto info = SkImageInfo::Make(dstSize,
827cb93a386Sopenharmony_ci                                      kRGBA_8888_SkColorType,
828cb93a386Sopenharmony_ci                                      this->colorInfo().alphaType(),
829cb93a386Sopenharmony_ci                                      dstColorSpace);
830cb93a386Sopenharmony_ci        // TODO: Incorporate the YUV conversion into last pass of rescaling.
831cb93a386Sopenharmony_ci        auto tempFC = this->rescale(info,
832cb93a386Sopenharmony_ci                                    kTopLeft_GrSurfaceOrigin,
833cb93a386Sopenharmony_ci                                    srcRect,
834cb93a386Sopenharmony_ci                                    rescaleGamma,
835cb93a386Sopenharmony_ci                                    rescaleMode);
836cb93a386Sopenharmony_ci        if (!tempFC) {
837cb93a386Sopenharmony_ci            callback(callbackContext, nullptr);
838cb93a386Sopenharmony_ci            return;
839cb93a386Sopenharmony_ci        }
840cb93a386Sopenharmony_ci        SkASSERT(SkColorSpace::Equals(tempFC->colorInfo().colorSpace(), info.colorSpace()));
841cb93a386Sopenharmony_ci        SkASSERT(tempFC->origin() == kTopLeft_GrSurfaceOrigin);
842cb93a386Sopenharmony_ci        x = y = 0;
843cb93a386Sopenharmony_ci        srcView = tempFC->readSurfaceView();
844cb93a386Sopenharmony_ci    } else if (!srcView.asTextureProxy()) {
845cb93a386Sopenharmony_ci        srcView = GrSurfaceProxyView::Copy(fContext,
846cb93a386Sopenharmony_ci                                           std::move(srcView),
847cb93a386Sopenharmony_ci                                           GrMipmapped::kNo,
848cb93a386Sopenharmony_ci                                           srcRect,
849cb93a386Sopenharmony_ci                                           SkBackingFit::kApprox,
850cb93a386Sopenharmony_ci                                           SkBudgeted::kYes);
851cb93a386Sopenharmony_ci        if (!srcView) {
852cb93a386Sopenharmony_ci            // If we can't get a texture copy of the contents then give up.
853cb93a386Sopenharmony_ci            callback(callbackContext, nullptr);
854cb93a386Sopenharmony_ci            return;
855cb93a386Sopenharmony_ci        }
856cb93a386Sopenharmony_ci        SkASSERT(srcView.asTextureProxy());
857cb93a386Sopenharmony_ci        x = y = 0;
858cb93a386Sopenharmony_ci    }
859cb93a386Sopenharmony_ci
860cb93a386Sopenharmony_ci    auto yInfo = SkImageInfo::MakeA8(dstSize);
861cb93a386Sopenharmony_ci    auto yFC = dContext->priv().makeSFCWithFallback(yInfo, SkBackingFit::kApprox);
862cb93a386Sopenharmony_ci
863cb93a386Sopenharmony_ci    auto uvInfo = yInfo.makeWH(yInfo.width()/2, yInfo.height()/2);
864cb93a386Sopenharmony_ci    auto uFC = dContext->priv().makeSFCWithFallback(uvInfo, SkBackingFit::kApprox);
865cb93a386Sopenharmony_ci    auto vFC = dContext->priv().makeSFCWithFallback(uvInfo, SkBackingFit::kApprox);
866cb93a386Sopenharmony_ci
867cb93a386Sopenharmony_ci    if (!yFC || !uFC || !vFC) {
868cb93a386Sopenharmony_ci        callback(callbackContext, nullptr);
869cb93a386Sopenharmony_ci        return;
870cb93a386Sopenharmony_ci    }
871cb93a386Sopenharmony_ci
872cb93a386Sopenharmony_ci    float baseM[20];
873cb93a386Sopenharmony_ci    SkColorMatrix_RGB2YUV(yuvColorSpace, baseM);
874cb93a386Sopenharmony_ci
875cb93a386Sopenharmony_ci    // TODO: Use one transfer buffer for all three planes to reduce map/unmap cost?
876cb93a386Sopenharmony_ci
877cb93a386Sopenharmony_ci    auto texMatrix = SkMatrix::Translate(x, y);
878cb93a386Sopenharmony_ci
879cb93a386Sopenharmony_ci    auto [readCT, offsetAlignment] =
880cb93a386Sopenharmony_ci            this->caps()->supportedReadPixelsColorType(yFC->colorInfo().colorType(),
881cb93a386Sopenharmony_ci                                                       yFC->asSurfaceProxy()->backendFormat(),
882cb93a386Sopenharmony_ci                                                       GrColorType::kAlpha_8);
883cb93a386Sopenharmony_ci    if (readCT == GrColorType::kUnknown) {
884cb93a386Sopenharmony_ci        callback(callbackContext, nullptr);
885cb93a386Sopenharmony_ci        return;
886cb93a386Sopenharmony_ci    }
887cb93a386Sopenharmony_ci    bool doSynchronousRead = !this->caps()->transferFromSurfaceToBufferSupport() ||
888cb93a386Sopenharmony_ci                             !offsetAlignment;
889cb93a386Sopenharmony_ci    PixelTransferResult yTransfer, uTransfer, vTransfer;
890cb93a386Sopenharmony_ci
891cb93a386Sopenharmony_ci    // This matrix generates (r,g,b,a) = (0, 0, 0, y)
892cb93a386Sopenharmony_ci    float yM[20];
893cb93a386Sopenharmony_ci    std::fill_n(yM, 15, 0.f);
894cb93a386Sopenharmony_ci    std::copy_n(baseM + 0, 5, yM + 15);
895cb93a386Sopenharmony_ci
896cb93a386Sopenharmony_ci    auto yFP = GrTextureEffect::Make(srcView, this->colorInfo().alphaType(), texMatrix);
897cb93a386Sopenharmony_ci    yFP = GrFragmentProcessor::ColorMatrix(std::move(yFP),
898cb93a386Sopenharmony_ci                                           yM,
899cb93a386Sopenharmony_ci                                           /*unpremulInput=*/false,
900cb93a386Sopenharmony_ci                                           /*clampRGBOutput=*/true,
901cb93a386Sopenharmony_ci                                           /*premulOutput=*/false);
902cb93a386Sopenharmony_ci    yFC->fillWithFP(std::move(yFP));
903cb93a386Sopenharmony_ci    if (!doSynchronousRead) {
904cb93a386Sopenharmony_ci        yTransfer = yFC->transferPixels(GrColorType::kAlpha_8,
905cb93a386Sopenharmony_ci                                        SkIRect::MakeSize(yFC->dimensions()));
906cb93a386Sopenharmony_ci        if (!yTransfer.fTransferBuffer) {
907cb93a386Sopenharmony_ci            callback(callbackContext, nullptr);
908cb93a386Sopenharmony_ci            return;
909cb93a386Sopenharmony_ci        }
910cb93a386Sopenharmony_ci    }
911cb93a386Sopenharmony_ci
912cb93a386Sopenharmony_ci    texMatrix.preScale(2.f, 2.f);
913cb93a386Sopenharmony_ci    // This matrix generates (r,g,b,a) = (0, 0, 0, u)
914cb93a386Sopenharmony_ci    float uM[20];
915cb93a386Sopenharmony_ci    std::fill_n(uM, 15, 0.f);
916cb93a386Sopenharmony_ci    std::copy_n(baseM + 5, 5, uM + 15);
917cb93a386Sopenharmony_ci
918cb93a386Sopenharmony_ci    auto uFP = GrTextureEffect::Make(srcView,
919cb93a386Sopenharmony_ci                                     this->colorInfo().alphaType(),
920cb93a386Sopenharmony_ci                                     texMatrix,
921cb93a386Sopenharmony_ci                                     GrSamplerState::Filter::kLinear);
922cb93a386Sopenharmony_ci    uFP = GrFragmentProcessor::ColorMatrix(std::move(uFP),
923cb93a386Sopenharmony_ci                                           uM,
924cb93a386Sopenharmony_ci                                           /*unpremulInput=*/false,
925cb93a386Sopenharmony_ci                                           /*clampRGBOutput=*/true,
926cb93a386Sopenharmony_ci                                           /*premulOutput=*/false);
927cb93a386Sopenharmony_ci    uFC->fillWithFP(std::move(uFP));
928cb93a386Sopenharmony_ci    if (!doSynchronousRead) {
929cb93a386Sopenharmony_ci        uTransfer = uFC->transferPixels(GrColorType::kAlpha_8,
930cb93a386Sopenharmony_ci                                        SkIRect::MakeSize(uFC->dimensions()));
931cb93a386Sopenharmony_ci        if (!uTransfer.fTransferBuffer) {
932cb93a386Sopenharmony_ci            callback(callbackContext, nullptr);
933cb93a386Sopenharmony_ci            return;
934cb93a386Sopenharmony_ci        }
935cb93a386Sopenharmony_ci    }
936cb93a386Sopenharmony_ci
937cb93a386Sopenharmony_ci    // This matrix generates (r,g,b,a) = (0, 0, 0, v)
938cb93a386Sopenharmony_ci    float vM[20];
939cb93a386Sopenharmony_ci    std::fill_n(vM, 15, 0.f);
940cb93a386Sopenharmony_ci    std::copy_n(baseM + 10, 5, vM + 15);
941cb93a386Sopenharmony_ci    auto vFP = GrTextureEffect::Make(std::move(srcView),
942cb93a386Sopenharmony_ci                                     this->colorInfo().alphaType(),
943cb93a386Sopenharmony_ci                                     texMatrix,
944cb93a386Sopenharmony_ci                                     GrSamplerState::Filter::kLinear);
945cb93a386Sopenharmony_ci    vFP = GrFragmentProcessor::ColorMatrix(std::move(vFP),
946cb93a386Sopenharmony_ci                                           vM,
947cb93a386Sopenharmony_ci                                           /*unpremulInput=*/false,
948cb93a386Sopenharmony_ci                                           /*clampRGBOutput=*/true,
949cb93a386Sopenharmony_ci                                           /*premulOutput=*/false);
950cb93a386Sopenharmony_ci    vFC->fillWithFP(std::move(vFP));
951cb93a386Sopenharmony_ci
952cb93a386Sopenharmony_ci    if (!doSynchronousRead) {
953cb93a386Sopenharmony_ci        vTransfer = vFC->transferPixels(GrColorType::kAlpha_8,
954cb93a386Sopenharmony_ci                                         SkIRect::MakeSize(vFC->dimensions()));
955cb93a386Sopenharmony_ci        if (!vTransfer.fTransferBuffer) {
956cb93a386Sopenharmony_ci            callback(callbackContext, nullptr);
957cb93a386Sopenharmony_ci            return;
958cb93a386Sopenharmony_ci        }
959cb93a386Sopenharmony_ci    }
960cb93a386Sopenharmony_ci
961cb93a386Sopenharmony_ci    if (doSynchronousRead) {
962cb93a386Sopenharmony_ci        GrPixmap yPmp = GrPixmap::Allocate(yInfo);
963cb93a386Sopenharmony_ci        GrPixmap uPmp = GrPixmap::Allocate(uvInfo);
964cb93a386Sopenharmony_ci        GrPixmap vPmp = GrPixmap::Allocate(uvInfo);
965cb93a386Sopenharmony_ci        if (!yFC->readPixels(dContext, yPmp, {0, 0}) ||
966cb93a386Sopenharmony_ci            !uFC->readPixels(dContext, uPmp, {0, 0}) ||
967cb93a386Sopenharmony_ci            !vFC->readPixels(dContext, vPmp, {0, 0})) {
968cb93a386Sopenharmony_ci            callback(callbackContext, nullptr);
969cb93a386Sopenharmony_ci            return;
970cb93a386Sopenharmony_ci        }
971cb93a386Sopenharmony_ci        auto result = std::make_unique<AsyncReadResult>(dContext->directContextID());
972cb93a386Sopenharmony_ci        result->addCpuPlane(yPmp.pixelStorage(), yPmp.rowBytes());
973cb93a386Sopenharmony_ci        result->addCpuPlane(uPmp.pixelStorage(), uPmp.rowBytes());
974cb93a386Sopenharmony_ci        result->addCpuPlane(vPmp.pixelStorage(), vPmp.rowBytes());
975cb93a386Sopenharmony_ci        callback(callbackContext, std::move(result));
976cb93a386Sopenharmony_ci        return;
977cb93a386Sopenharmony_ci    }
978cb93a386Sopenharmony_ci
979cb93a386Sopenharmony_ci    struct FinishContext {
980cb93a386Sopenharmony_ci        ReadPixelsCallback* fClientCallback;
981cb93a386Sopenharmony_ci        ReadPixelsContext fClientContext;
982cb93a386Sopenharmony_ci        GrClientMappedBufferManager* fMappedBufferManager;
983cb93a386Sopenharmony_ci        SkISize fSize;
984cb93a386Sopenharmony_ci        size_t fBufferAlignment;
985cb93a386Sopenharmony_ci        PixelTransferResult fYTransfer;
986cb93a386Sopenharmony_ci        PixelTransferResult fUTransfer;
987cb93a386Sopenharmony_ci        PixelTransferResult fVTransfer;
988cb93a386Sopenharmony_ci    };
989cb93a386Sopenharmony_ci    // Assumption is that the caller would like to flush. We could take a parameter or require an
990cb93a386Sopenharmony_ci    // explicit flush from the caller. We'd have to have a way to defer attaching the finish
991cb93a386Sopenharmony_ci    // callback to GrGpu until after the next flush that flushes our op list, though.
992cb93a386Sopenharmony_ci    auto* finishContext = new FinishContext{callback,
993cb93a386Sopenharmony_ci                                            callbackContext,
994cb93a386Sopenharmony_ci                                            dContext->priv().clientMappedBufferManager(),
995cb93a386Sopenharmony_ci                                            dstSize,
996cb93a386Sopenharmony_ci                                            this->caps()->transferBufferAlignment(),
997cb93a386Sopenharmony_ci                                            std::move(yTransfer),
998cb93a386Sopenharmony_ci                                            std::move(uTransfer),
999cb93a386Sopenharmony_ci                                            std::move(vTransfer)};
1000cb93a386Sopenharmony_ci    auto finishCallback = [](GrGpuFinishedContext c) {
1001cb93a386Sopenharmony_ci        const auto* context = reinterpret_cast<const FinishContext*>(c);
1002cb93a386Sopenharmony_ci        auto manager = context->fMappedBufferManager;
1003cb93a386Sopenharmony_ci        auto result = std::make_unique<AsyncReadResult>(manager->owningDirectContext());
1004cb93a386Sopenharmony_ci        size_t rowBytes = SkToSizeT(context->fSize.width());
1005cb93a386Sopenharmony_ci        rowBytes = SkAlignTo(rowBytes, context->fBufferAlignment);
1006cb93a386Sopenharmony_ci        if (!result->addTransferResult(context->fYTransfer, context->fSize, rowBytes, manager)) {
1007cb93a386Sopenharmony_ci            (*context->fClientCallback)(context->fClientContext, nullptr);
1008cb93a386Sopenharmony_ci            delete context;
1009cb93a386Sopenharmony_ci            return;
1010cb93a386Sopenharmony_ci        }
1011cb93a386Sopenharmony_ci        rowBytes = SkToSizeT(context->fSize.width()) / 2;
1012cb93a386Sopenharmony_ci        rowBytes = SkAlignTo(rowBytes, context->fBufferAlignment);
1013cb93a386Sopenharmony_ci        SkISize uvSize = {context->fSize.width() / 2, context->fSize.height() / 2};
1014cb93a386Sopenharmony_ci        if (!result->addTransferResult(context->fUTransfer, uvSize, rowBytes, manager)) {
1015cb93a386Sopenharmony_ci            (*context->fClientCallback)(context->fClientContext, nullptr);
1016cb93a386Sopenharmony_ci            delete context;
1017cb93a386Sopenharmony_ci            return;
1018cb93a386Sopenharmony_ci        }
1019cb93a386Sopenharmony_ci        if (!result->addTransferResult(context->fVTransfer, uvSize, rowBytes, manager)) {
1020cb93a386Sopenharmony_ci            (*context->fClientCallback)(context->fClientContext, nullptr);
1021cb93a386Sopenharmony_ci            delete context;
1022cb93a386Sopenharmony_ci            return;
1023cb93a386Sopenharmony_ci        }
1024cb93a386Sopenharmony_ci        (*context->fClientCallback)(context->fClientContext, std::move(result));
1025cb93a386Sopenharmony_ci        delete context;
1026cb93a386Sopenharmony_ci    };
1027cb93a386Sopenharmony_ci    GrFlushInfo flushInfo;
1028cb93a386Sopenharmony_ci    flushInfo.fFinishedContext = finishContext;
1029cb93a386Sopenharmony_ci    flushInfo.fFinishedProc = finishCallback;
1030cb93a386Sopenharmony_ci    dContext->priv().flushSurface(this->asSurfaceProxy(),
1031cb93a386Sopenharmony_ci                                  SkSurface::BackendSurfaceAccess::kNoAccess,
1032cb93a386Sopenharmony_ci                                  flushInfo);
1033cb93a386Sopenharmony_ci}
1034cb93a386Sopenharmony_ci
1035cb93a386Sopenharmony_cisk_sp<GrRenderTask> SurfaceContext::copy(sk_sp<GrSurfaceProxy> src,
1036cb93a386Sopenharmony_ci                                         SkIRect srcRect,
1037cb93a386Sopenharmony_ci                                         SkIPoint dstPoint) {
1038cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1039cb93a386Sopenharmony_ci    RETURN_NULLPTR_IF_ABANDONED
1040cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1041cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceContext", "copy", fContext);
1042cb93a386Sopenharmony_ci
1043cb93a386Sopenharmony_ci    const GrCaps* caps = fContext->priv().caps();
1044cb93a386Sopenharmony_ci
1045cb93a386Sopenharmony_ci    SkASSERT(src->backendFormat().textureType() != GrTextureType::kExternal);
1046cb93a386Sopenharmony_ci    SkASSERT(src->backendFormat() == this->asSurfaceProxy()->backendFormat());
1047cb93a386Sopenharmony_ci
1048cb93a386Sopenharmony_ci    if (this->asSurfaceProxy()->framebufferOnly()) {
1049cb93a386Sopenharmony_ci        return nullptr;
1050cb93a386Sopenharmony_ci    }
1051cb93a386Sopenharmony_ci
1052cb93a386Sopenharmony_ci    if (!caps->canCopySurface(this->asSurfaceProxy(), src.get(), srcRect, dstPoint)) {
1053cb93a386Sopenharmony_ci        return nullptr;
1054cb93a386Sopenharmony_ci    }
1055cb93a386Sopenharmony_ci
1056cb93a386Sopenharmony_ci    return this->drawingManager()->newCopyRenderTask(std::move(src),
1057cb93a386Sopenharmony_ci                                                     srcRect,
1058cb93a386Sopenharmony_ci                                                     this->asSurfaceProxyRef(),
1059cb93a386Sopenharmony_ci                                                     dstPoint,
1060cb93a386Sopenharmony_ci                                                     this->origin());
1061cb93a386Sopenharmony_ci}
1062cb93a386Sopenharmony_ci
1063cb93a386Sopenharmony_cistd::unique_ptr<skgpu::SurfaceFillContext> SurfaceContext::rescale(const GrImageInfo& info,
1064cb93a386Sopenharmony_ci                                                                   GrSurfaceOrigin origin,
1065cb93a386Sopenharmony_ci                                                                   SkIRect srcRect,
1066cb93a386Sopenharmony_ci                                                                   RescaleGamma rescaleGamma,
1067cb93a386Sopenharmony_ci                                                                   RescaleMode rescaleMode) {
1068cb93a386Sopenharmony_ci    auto sfc = fContext->priv().makeSFCWithFallback(info,
1069cb93a386Sopenharmony_ci                                                    SkBackingFit::kExact,
1070cb93a386Sopenharmony_ci                                                    1,
1071cb93a386Sopenharmony_ci                                                    GrMipmapped::kNo,
1072cb93a386Sopenharmony_ci                                                    this->asSurfaceProxy()->isProtected(),
1073cb93a386Sopenharmony_ci                                                    origin);
1074cb93a386Sopenharmony_ci    if (!sfc || !this->rescaleInto(sfc.get(),
1075cb93a386Sopenharmony_ci                                   SkIRect::MakeSize(sfc->dimensions()),
1076cb93a386Sopenharmony_ci                                   srcRect,
1077cb93a386Sopenharmony_ci                                   rescaleGamma,
1078cb93a386Sopenharmony_ci                                   rescaleMode)) {
1079cb93a386Sopenharmony_ci        return nullptr;
1080cb93a386Sopenharmony_ci    }
1081cb93a386Sopenharmony_ci    return sfc;
1082cb93a386Sopenharmony_ci}
1083cb93a386Sopenharmony_ci
1084cb93a386Sopenharmony_cibool SurfaceContext::rescaleInto(skgpu::SurfaceFillContext* dst,
1085cb93a386Sopenharmony_ci                                 SkIRect dstRect,
1086cb93a386Sopenharmony_ci                                 SkIRect srcRect,
1087cb93a386Sopenharmony_ci                                 RescaleGamma rescaleGamma,
1088cb93a386Sopenharmony_ci                                 RescaleMode rescaleMode) {
1089cb93a386Sopenharmony_ci    SkASSERT(dst);
1090cb93a386Sopenharmony_ci    if (!SkIRect::MakeSize(dst->dimensions()).contains((dstRect))) {
1091cb93a386Sopenharmony_ci        return false;
1092cb93a386Sopenharmony_ci    }
1093cb93a386Sopenharmony_ci
1094cb93a386Sopenharmony_ci    auto rtProxy = this->asRenderTargetProxy();
1095cb93a386Sopenharmony_ci    if (rtProxy && rtProxy->wrapsVkSecondaryCB()) {
1096cb93a386Sopenharmony_ci        return false;
1097cb93a386Sopenharmony_ci    }
1098cb93a386Sopenharmony_ci
1099cb93a386Sopenharmony_ci    if (this->asSurfaceProxy()->framebufferOnly()) {
1100cb93a386Sopenharmony_ci        return false;
1101cb93a386Sopenharmony_ci    }
1102cb93a386Sopenharmony_ci
1103cb93a386Sopenharmony_ci    GrSurfaceProxyView texView = this->readSurfaceView();
1104cb93a386Sopenharmony_ci    if (!texView.asTextureProxy()) {
1105cb93a386Sopenharmony_ci        // TODO: If copying supported specifying a renderable copy then we could return the copy
1106cb93a386Sopenharmony_ci        // when there are no other conversions.
1107cb93a386Sopenharmony_ci        texView = GrSurfaceProxyView::Copy(fContext, std::move(texView), GrMipmapped::kNo, srcRect,
1108cb93a386Sopenharmony_ci                                           SkBackingFit::kApprox, SkBudgeted::kNo);
1109cb93a386Sopenharmony_ci        if (!texView) {
1110cb93a386Sopenharmony_ci            return false;
1111cb93a386Sopenharmony_ci        }
1112cb93a386Sopenharmony_ci        SkASSERT(texView.asTextureProxy());
1113cb93a386Sopenharmony_ci        srcRect = SkIRect::MakeSize(srcRect.size());
1114cb93a386Sopenharmony_ci    }
1115cb93a386Sopenharmony_ci
1116cb93a386Sopenharmony_ci    SkISize finalSize = dstRect.size();
1117cb93a386Sopenharmony_ci    if (finalSize == srcRect.size()) {
1118cb93a386Sopenharmony_ci        rescaleGamma = RescaleGamma::kSrc;
1119cb93a386Sopenharmony_ci        rescaleMode = RescaleMode::kNearest;
1120cb93a386Sopenharmony_ci    }
1121cb93a386Sopenharmony_ci
1122cb93a386Sopenharmony_ci    // Within a rescaling pass A is the input (if not null) and B is the output. At the end of the
1123cb93a386Sopenharmony_ci    // pass B is moved to A. If 'this' is the input on the first pass then tempA is null.
1124cb93a386Sopenharmony_ci    std::unique_ptr<skgpu::SurfaceFillContext> tempA;
1125cb93a386Sopenharmony_ci    std::unique_ptr<skgpu::SurfaceFillContext> tempB;
1126cb93a386Sopenharmony_ci
1127cb93a386Sopenharmony_ci    // Assume we should ignore the rescale linear request if the surface has no color space since
1128cb93a386Sopenharmony_ci    // it's unclear how we'd linearize from an unknown color space.
1129cb93a386Sopenharmony_ci    if (rescaleGamma == RescaleGamma::kLinear && this->colorInfo().colorSpace() &&
1130cb93a386Sopenharmony_ci        !this->colorInfo().colorSpace()->gammaIsLinear()) {
1131cb93a386Sopenharmony_ci        auto cs = this->colorInfo().colorSpace()->makeLinearGamma();
1132cb93a386Sopenharmony_ci        // We'll fall back to kRGBA_8888 if half float not supported.
1133cb93a386Sopenharmony_ci        GrImageInfo ii(GrColorType::kRGBA_F16,
1134cb93a386Sopenharmony_ci                       dst->colorInfo().alphaType(),
1135cb93a386Sopenharmony_ci                       std::move(cs),
1136cb93a386Sopenharmony_ci                       srcRect.size());
1137cb93a386Sopenharmony_ci        auto linearRTC = fContext->priv().makeSFCWithFallback(std::move(ii),
1138cb93a386Sopenharmony_ci                                                              SkBackingFit::kApprox,
1139cb93a386Sopenharmony_ci                                                              1,
1140cb93a386Sopenharmony_ci                                                              GrMipmapped::kNo,
1141cb93a386Sopenharmony_ci                                                              GrProtected::kNo,
1142cb93a386Sopenharmony_ci                                                              dst->origin());
1143cb93a386Sopenharmony_ci        if (!linearRTC) {
1144cb93a386Sopenharmony_ci            return false;
1145cb93a386Sopenharmony_ci        }
1146cb93a386Sopenharmony_ci        auto fp = GrTextureEffect::Make(std::move(texView),
1147cb93a386Sopenharmony_ci                                        this->colorInfo().alphaType(),
1148cb93a386Sopenharmony_ci                                        SkMatrix::Translate(srcRect.topLeft()),
1149cb93a386Sopenharmony_ci                                        GrSamplerState::Filter::kNearest,
1150cb93a386Sopenharmony_ci                                        GrSamplerState::MipmapMode::kNone);
1151cb93a386Sopenharmony_ci        fp = GrColorSpaceXformEffect::Make(std::move(fp),
1152cb93a386Sopenharmony_ci                                           this->colorInfo(),
1153cb93a386Sopenharmony_ci                                           linearRTC->colorInfo());
1154cb93a386Sopenharmony_ci        linearRTC->fillWithFP(std::move(fp));
1155cb93a386Sopenharmony_ci        texView = linearRTC->readSurfaceView();
1156cb93a386Sopenharmony_ci        SkASSERT(texView.asTextureProxy());
1157cb93a386Sopenharmony_ci        tempA = std::move(linearRTC);
1158cb93a386Sopenharmony_ci        srcRect = SkIRect::MakeSize(srcRect.size());
1159cb93a386Sopenharmony_ci    }
1160cb93a386Sopenharmony_ci
1161cb93a386Sopenharmony_ci    do {
1162cb93a386Sopenharmony_ci        SkISize nextDims = finalSize;
1163cb93a386Sopenharmony_ci        if (rescaleMode != RescaleMode::kNearest) {
1164cb93a386Sopenharmony_ci            if (srcRect.width() > finalSize.width()) {
1165cb93a386Sopenharmony_ci                nextDims.fWidth = std::max((srcRect.width() + 1)/2, finalSize.width());
1166cb93a386Sopenharmony_ci            } else if (srcRect.width() < finalSize.width()) {
1167cb93a386Sopenharmony_ci                nextDims.fWidth = std::min(srcRect.width()*2, finalSize.width());
1168cb93a386Sopenharmony_ci            }
1169cb93a386Sopenharmony_ci            if (srcRect.height() > finalSize.height()) {
1170cb93a386Sopenharmony_ci                nextDims.fHeight = std::max((srcRect.height() + 1)/2, finalSize.height());
1171cb93a386Sopenharmony_ci            } else if (srcRect.height() < finalSize.height()) {
1172cb93a386Sopenharmony_ci                nextDims.fHeight = std::min(srcRect.height()*2, finalSize.height());
1173cb93a386Sopenharmony_ci            }
1174cb93a386Sopenharmony_ci        }
1175cb93a386Sopenharmony_ci        auto input = tempA ? tempA.get() : this;
1176cb93a386Sopenharmony_ci        sk_sp<GrColorSpaceXform> xform;
1177cb93a386Sopenharmony_ci        skgpu::SurfaceFillContext* stepDst;
1178cb93a386Sopenharmony_ci        SkIRect stepDstRect;
1179cb93a386Sopenharmony_ci        if (nextDims == finalSize) {
1180cb93a386Sopenharmony_ci            stepDst = dst;
1181cb93a386Sopenharmony_ci            stepDstRect = dstRect;
1182cb93a386Sopenharmony_ci            xform = GrColorSpaceXform::Make(input->colorInfo(), dst->colorInfo());
1183cb93a386Sopenharmony_ci        } else {
1184cb93a386Sopenharmony_ci            GrImageInfo nextInfo(input->colorInfo(), nextDims);
1185cb93a386Sopenharmony_ci            tempB = fContext->priv().makeSFCWithFallback(nextInfo, SkBackingFit::kApprox);
1186cb93a386Sopenharmony_ci            if (!tempB) {
1187cb93a386Sopenharmony_ci                return false;
1188cb93a386Sopenharmony_ci            }
1189cb93a386Sopenharmony_ci            stepDst = tempB.get();
1190cb93a386Sopenharmony_ci            stepDstRect = SkIRect::MakeSize(tempB->dimensions());
1191cb93a386Sopenharmony_ci        }
1192cb93a386Sopenharmony_ci        std::unique_ptr<GrFragmentProcessor> fp;
1193cb93a386Sopenharmony_ci        if (rescaleMode == RescaleMode::kRepeatedCubic) {
1194cb93a386Sopenharmony_ci            auto dir = GrBicubicEffect::Direction::kXY;
1195cb93a386Sopenharmony_ci            if (nextDims.width() == srcRect.width()) {
1196cb93a386Sopenharmony_ci                dir = GrBicubicEffect::Direction::kY;
1197cb93a386Sopenharmony_ci            } else if (nextDims.height() == srcRect.height()) {
1198cb93a386Sopenharmony_ci                dir = GrBicubicEffect::Direction::kX;
1199cb93a386Sopenharmony_ci            }
1200cb93a386Sopenharmony_ci            static constexpr auto kWM     = GrSamplerState::WrapMode::kClamp;
1201cb93a386Sopenharmony_ci            static constexpr auto kKernel = GrBicubicEffect::gCatmullRom;
1202cb93a386Sopenharmony_ci            fp = GrBicubicEffect::MakeSubset(std::move(texView),
1203cb93a386Sopenharmony_ci                                             input->colorInfo().alphaType(),
1204cb93a386Sopenharmony_ci                                             SkMatrix::I(),
1205cb93a386Sopenharmony_ci                                             kWM,
1206cb93a386Sopenharmony_ci                                             kWM,
1207cb93a386Sopenharmony_ci                                             SkRect::Make(srcRect),
1208cb93a386Sopenharmony_ci                                             kKernel,
1209cb93a386Sopenharmony_ci                                             dir,
1210cb93a386Sopenharmony_ci                                             *this->caps());
1211cb93a386Sopenharmony_ci        } else {
1212cb93a386Sopenharmony_ci            auto filter = rescaleMode == RescaleMode::kNearest ? GrSamplerState::Filter::kNearest
1213cb93a386Sopenharmony_ci                                                               : GrSamplerState::Filter::kLinear;
1214cb93a386Sopenharmony_ci            auto srcRectF = SkRect::Make(srcRect);
1215cb93a386Sopenharmony_ci            fp = GrTextureEffect::MakeSubset(std::move(texView),
1216cb93a386Sopenharmony_ci                                             this->colorInfo().alphaType(),
1217cb93a386Sopenharmony_ci                                             SkMatrix::I(),
1218cb93a386Sopenharmony_ci                                             {filter, GrSamplerState::MipmapMode::kNone},
1219cb93a386Sopenharmony_ci                                             srcRectF,
1220cb93a386Sopenharmony_ci                                             srcRectF,
1221cb93a386Sopenharmony_ci                                             *this->caps());
1222cb93a386Sopenharmony_ci        }
1223cb93a386Sopenharmony_ci        if (xform) {
1224cb93a386Sopenharmony_ci            fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(xform));
1225cb93a386Sopenharmony_ci        }
1226cb93a386Sopenharmony_ci        stepDst->fillRectToRectWithFP(srcRect, stepDstRect, std::move(fp));
1227cb93a386Sopenharmony_ci        texView = stepDst->readSurfaceView();
1228cb93a386Sopenharmony_ci        tempA = std::move(tempB);
1229cb93a386Sopenharmony_ci        srcRect = SkIRect::MakeSize(nextDims);
1230cb93a386Sopenharmony_ci    } while (srcRect.size() != finalSize);
1231cb93a386Sopenharmony_ci    return true;
1232cb93a386Sopenharmony_ci}
1233cb93a386Sopenharmony_ci
1234cb93a386Sopenharmony_ciSurfaceContext::PixelTransferResult SurfaceContext::transferPixels(GrColorType dstCT,
1235cb93a386Sopenharmony_ci                                                                   const SkIRect& rect) {
1236cb93a386Sopenharmony_ci    SkASSERT(rect.fLeft >= 0 && rect.fRight <= this->width());
1237cb93a386Sopenharmony_ci    SkASSERT(rect.fTop >= 0 && rect.fBottom <= this->height());
1238cb93a386Sopenharmony_ci    auto direct = fContext->asDirectContext();
1239cb93a386Sopenharmony_ci    if (!direct) {
1240cb93a386Sopenharmony_ci        return {};
1241cb93a386Sopenharmony_ci    }
1242cb93a386Sopenharmony_ci    auto rtProxy = this->asRenderTargetProxy();
1243cb93a386Sopenharmony_ci    if (rtProxy && rtProxy->wrapsVkSecondaryCB()) {
1244cb93a386Sopenharmony_ci        return {};
1245cb93a386Sopenharmony_ci    }
1246cb93a386Sopenharmony_ci
1247cb93a386Sopenharmony_ci    auto proxy = this->asSurfaceProxy();
1248cb93a386Sopenharmony_ci    auto supportedRead = this->caps()->supportedReadPixelsColorType(this->colorInfo().colorType(),
1249cb93a386Sopenharmony_ci                                                                    proxy->backendFormat(), dstCT);
1250cb93a386Sopenharmony_ci    // Fail if read color type does not have all of dstCT's color channels and those missing color
1251cb93a386Sopenharmony_ci    // channels are in the src.
1252cb93a386Sopenharmony_ci    uint32_t dstChannels = GrColorTypeChannelFlags(dstCT);
1253cb93a386Sopenharmony_ci    uint32_t legalReadChannels = GrColorTypeChannelFlags(supportedRead.fColorType);
1254cb93a386Sopenharmony_ci    uint32_t srcChannels = GrColorTypeChannelFlags(this->colorInfo().colorType());
1255cb93a386Sopenharmony_ci    if ((~legalReadChannels & dstChannels) & srcChannels) {
1256cb93a386Sopenharmony_ci        return {};
1257cb93a386Sopenharmony_ci    }
1258cb93a386Sopenharmony_ci
1259cb93a386Sopenharmony_ci    if (!this->caps()->transferFromSurfaceToBufferSupport() ||
1260cb93a386Sopenharmony_ci        !supportedRead.fOffsetAlignmentForTransferBuffer) {
1261cb93a386Sopenharmony_ci        return {};
1262cb93a386Sopenharmony_ci    }
1263cb93a386Sopenharmony_ci
1264cb93a386Sopenharmony_ci    size_t rowBytes = GrColorTypeBytesPerPixel(supportedRead.fColorType) * rect.width();
1265cb93a386Sopenharmony_ci    rowBytes = SkAlignTo(rowBytes, this->caps()->transferBufferAlignment());
1266cb93a386Sopenharmony_ci    size_t size = rowBytes * rect.height();
1267cb93a386Sopenharmony_ci    // By using kStream_GrAccessPattern here, we are not able to cache and reuse the buffer for
1268cb93a386Sopenharmony_ci    // multiple reads. Switching to kDynamic_GrAccessPattern would allow for this, however doing
1269cb93a386Sopenharmony_ci    // so causes a crash in a chromium test. See skbug.com/11297
1270cb93a386Sopenharmony_ci    auto buffer = direct->priv().resourceProvider()->createBuffer(
1271cb93a386Sopenharmony_ci            size, GrGpuBufferType::kXferGpuToCpu, GrAccessPattern::kStream_GrAccessPattern);
1272cb93a386Sopenharmony_ci    if (!buffer) {
1273cb93a386Sopenharmony_ci        return {};
1274cb93a386Sopenharmony_ci    }
1275cb93a386Sopenharmony_ci    auto srcRect = rect;
1276cb93a386Sopenharmony_ci    bool flip = this->origin() == kBottomLeft_GrSurfaceOrigin;
1277cb93a386Sopenharmony_ci    if (flip) {
1278cb93a386Sopenharmony_ci        srcRect = SkIRect::MakeLTRB(rect.fLeft, this->height() - rect.fBottom, rect.fRight,
1279cb93a386Sopenharmony_ci                                    this->height() - rect.fTop);
1280cb93a386Sopenharmony_ci    }
1281cb93a386Sopenharmony_ci    this->drawingManager()->newTransferFromRenderTask(this->asSurfaceProxyRef(), srcRect,
1282cb93a386Sopenharmony_ci                                                      this->colorInfo().colorType(),
1283cb93a386Sopenharmony_ci                                                      supportedRead.fColorType, buffer, 0);
1284cb93a386Sopenharmony_ci    PixelTransferResult result;
1285cb93a386Sopenharmony_ci    result.fTransferBuffer = std::move(buffer);
1286cb93a386Sopenharmony_ci    auto at = this->colorInfo().alphaType();
1287cb93a386Sopenharmony_ci    if (supportedRead.fColorType != dstCT || flip) {
1288cb93a386Sopenharmony_ci        result.fPixelConverter = [w = rect.width(), h = rect.height(), dstCT, supportedRead, at](
1289cb93a386Sopenharmony_ci                void* dst, const void* src) {
1290cb93a386Sopenharmony_ci            GrImageInfo srcInfo(supportedRead.fColorType, at, nullptr, w, h);
1291cb93a386Sopenharmony_ci            GrImageInfo dstInfo(dstCT,                    at, nullptr, w, h);
1292cb93a386Sopenharmony_ci            GrConvertPixels( GrPixmap(dstInfo, dst, dstInfo.minRowBytes()),
1293cb93a386Sopenharmony_ci                            GrCPixmap(srcInfo, src, srcInfo.minRowBytes()));
1294cb93a386Sopenharmony_ci        };
1295cb93a386Sopenharmony_ci    }
1296cb93a386Sopenharmony_ci    return result;
1297cb93a386Sopenharmony_ci}
1298cb93a386Sopenharmony_ci
1299cb93a386Sopenharmony_ci#ifdef SK_DEBUG
1300cb93a386Sopenharmony_civoid SurfaceContext::validate() const {
1301cb93a386Sopenharmony_ci    SkASSERT(fReadView.proxy());
1302cb93a386Sopenharmony_ci    fReadView.proxy()->validate(fContext);
1303cb93a386Sopenharmony_ci    if (this->colorInfo().colorType() != GrColorType::kUnknown) {
1304cb93a386Sopenharmony_ci        SkASSERT(fContext->priv().caps()->areColorTypeAndFormatCompatible(
1305cb93a386Sopenharmony_ci                this->colorInfo().colorType(), fReadView.proxy()->backendFormat()));
1306cb93a386Sopenharmony_ci    }
1307cb93a386Sopenharmony_ci    this->onValidate();
1308cb93a386Sopenharmony_ci}
1309cb93a386Sopenharmony_ci#endif
1310cb93a386Sopenharmony_ci
1311cb93a386Sopenharmony_ci} // namespace skgpu
1312