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