Don't require color type to make proxy copies.

Bug: skia:10078

Change-Id: I3ce0d97f8ada55403cc3f88bb16659085449ea29
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/281207
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
Brian Salomon 2020-04-02 12:50:34 -04:00 committed by Skia Commit-Bot
parent 9ce08e81f1
commit c524378621
25 changed files with 223 additions and 226 deletions

View File

@ -183,9 +183,11 @@ public:
} }
} }
protected: protected:
GrSurfaceProxyView onGenerateTexture(GrRecordingContext* ctx, const SkImageInfo& info, GrSurfaceProxyView onGenerateTexture(GrRecordingContext* ctx,
const SkIPoint& origin, GrMipMapped mipMapped, const SkImageInfo& info,
GrImageTexGenPolicy) override { const SkIPoint& origin,
GrMipMapped mipMapped,
GrImageTexGenPolicy policy) override {
SkASSERT(ctx); SkASSERT(ctx);
SkASSERT(ctx == fCtx.get()); SkASSERT(ctx == fCtx.get());
@ -193,17 +195,16 @@ protected:
return {}; return {};
} }
if (origin.fX == 0 && origin.fY == 0 && info.dimensions() == fView.proxy()->dimensions()) { if (origin.fX == 0 && origin.fY == 0 && info.dimensions() == fView.proxy()->dimensions() &&
policy == GrImageTexGenPolicy::kDraw) {
return fView; return fView;
} }
auto budgeted = policy == GrImageTexGenPolicy::kNew_Uncached_Budgeted ? SkBudgeted::kYes
// TODO: When we update this function to return a view instead of just a proxy then we can : SkBudgeted::kNo;
// remove the extra ref that happens when we call asTextureProxyRef. return GrSurfaceProxyView::Copy(
return GrSurfaceProxy::Copy( fCtx.get(), fView, mipMapped,
fCtx.get(), fView.proxy(), fView.origin(),
SkColorTypeToGrColorType(info.colorType()), mipMapped,
SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height()), SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height()),
SkBackingFit::kExact, SkBudgeted::kYes); SkBackingFit::kExact, budgeted);
} }
private: private:

View File

@ -484,7 +484,6 @@ public:
fAlphaType); fAlphaType);
} }
// TODO: move all the logic here into the subset-flavor GrSurfaceProxy::copy?
sk_sp<SkImage> onAsImage(const SkIRect* subset) const override { sk_sp<SkImage> onAsImage(const SkIRect* subset) const override {
GrSurfaceProxy* proxy = fView.proxy(); GrSurfaceProxy* proxy = fView.proxy();
if (subset) { if (subset) {
@ -495,11 +494,9 @@ public:
fColorSpace); fColorSpace);
} }
GrSurfaceProxyView subsetView = auto subsetView = GrSurfaceProxyView::Copy(fContext, fView, GrMipMapped::kNo, *subset,
GrSurfaceProxy::Copy(fContext, proxy, fView.origin(), fColorType, SkBackingFit::kExact, SkBudgeted::kYes);
GrMipMapped::kNo, *subset, SkBackingFit::kExact, if (!subsetView) {
SkBudgeted::kYes);
if (!subsetView.proxy()) {
return nullptr; return nullptr;
} }
SkASSERT(subsetView.asTextureProxy()); SkASSERT(subsetView.asTextureProxy());

View File

@ -210,9 +210,8 @@ GrSurfaceProxyView GrAHardwareBufferImageGenerator::onGenerateTexture(
? SkBudgeted::kNo ? SkBudgeted::kNo
: SkBudgeted::kYes; : SkBudgeted::kYes;
GrColorType grColorType = SkColorTypeToGrColorType(this->getInfo().colorType()); return GrSurfaceProxyView::Copy(context, std::move(texProxyView), mipMapped, subset,
return GrSurfaceProxy::Copy(context, texProxyView.proxy(), texProxyView.origin(), grColorType, SkBackingFit::kExact, budgeted);
mipMapped, subset, SkBackingFit::kExact, budgeted);
} }
bool GrAHardwareBufferImageGenerator::onIsValid(GrContext* context) const { bool GrAHardwareBufferImageGenerator::onIsValid(GrContext* context) const {

View File

@ -219,7 +219,8 @@ GrSurfaceProxyView GrBackendTextureImageGenerator::onGenerateTexture(
? SkBudgeted::kNo ? SkBudgeted::kNo
: SkBudgeted::kYes; : SkBudgeted::kYes;
return GrSurfaceProxy::Copy(context, proxy.get(), fSurfaceOrigin, grColorType, mipMapped, auto copy = GrSurfaceProxy::Copy(context, proxy.get(), fSurfaceOrigin, mipMapped, subset,
subset, SkBackingFit::kExact, budgeted); SkBackingFit::kExact, budgeted);
return {std::move(copy), fSurfaceOrigin, readSwizzle};
} }
} }

View File

@ -71,7 +71,7 @@ GrSurfaceProxyView GrBitmapTextureMaker::refOriginalTextureProxyView(GrMipMapped
swizzle = this->context()->priv().caps()->getReadSwizzle(proxy->backendFormat(), swizzle = this->context()->priv().caps()->getReadSwizzle(proxy->backendFormat(),
this->colorType()); this->colorType());
if (mipMapped == GrMipMapped::kNo || proxy->mipMapped() == GrMipMapped::kYes) { if (mipMapped == GrMipMapped::kNo || proxy->mipMapped() == GrMipMapped::kYes) {
return GrSurfaceProxyView(std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle); return {std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle};
} }
} }
} }
@ -96,7 +96,7 @@ GrSurfaceProxyView GrBitmapTextureMaker::refOriginalTextureProxyView(GrMipMapped
if (fKey.isValid()) { if (fKey.isValid()) {
installKey(proxy.get()); installKey(proxy.get());
} }
return GrSurfaceProxyView(std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle); return {std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle};
} }
} }
@ -107,26 +107,23 @@ GrSurfaceProxyView GrBitmapTextureMaker::refOriginalTextureProxyView(GrMipMapped
// We need a mipped proxy, but we found a proxy earlier that wasn't mipped. Thus we generate // We need a mipped proxy, but we found a proxy earlier that wasn't mipped. Thus we generate
// a new mipped surface and copy the original proxy into the base layer. We will then let // a new mipped surface and copy the original proxy into the base layer. We will then let
// the gpu generate the rest of the mips. // the gpu generate the rest of the mips.
GrColorType srcColorType = SkColorTypeToGrColorType(fBitmap.colorType()); auto mippedProxy = GrCopyBaseMipMapToTextureProxy(this->context(), proxy.get(),
auto mippedView = GrCopyBaseMipMapToTextureProxy(this->context(), proxy.get(), kTopLeft_GrSurfaceOrigin);
kTopLeft_GrSurfaceOrigin, srcColorType); if (!mippedProxy) {
if (auto mippedProxy = mippedView.asTextureProxy()) { // We failed to make a mipped proxy with the base copied into it. This could have
// In this case we are stealing the key from the original proxy which should only happen // been from failure to make the proxy or failure to do the copy. Thus we will fall
// when we have just generated mipmaps for an originally unmipped proxy/texture. This // back to just using the non mipped proxy; See skbug.com/7094.
// means that all future uses of the key will access the mipmapped version. The texture return {std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle};
// backing the unmipped version will remain in the resource cache until the last texture
// proxy referencing it is deleted at which time it too will be deleted or recycled.
SkASSERT(proxy->getUniqueKey() == fKey);
SkASSERT(mippedView.origin() == kTopLeft_GrSurfaceOrigin);
SkASSERT(mippedView.swizzle() == swizzle);
proxyProvider->removeUniqueKeyFromProxy(proxy.get());
installKey(mippedProxy);
return mippedView;
} }
// We failed to make a mipped proxy with the base copied into it. This could have // In this case we are stealing the key from the original proxy which should only happen
// been from failure to make the proxy or failure to do the copy. Thus we will fall // when we have just generated mipmaps for an originally unmipped proxy/texture. This
// back to just using the non mipped proxy; See skbug.com/7094. // means that all future uses of the key will access the mipmapped version. The texture
return GrSurfaceProxyView(std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle); // backing the unmipped version will remain in the resource cache until the last texture
// proxy referencing it is deleted at which time it too will be deleted or recycled.
SkASSERT(proxy->getUniqueKey() == fKey);
proxyProvider->removeUniqueKeyFromProxy(proxy.get());
installKey(mippedProxy->asTextureProxy());
return {std::move(mippedProxy), kTopLeft_GrSurfaceOrigin, swizzle};
} }
return {}; return {};
} }

View File

@ -152,8 +152,11 @@ std::unique_ptr<GrRenderTargetContext> GrRenderTargetContext::Make(
} }
const GrBackendFormat& format = proxy->backendFormat(); const GrBackendFormat& format = proxy->backendFormat();
GrSwizzle readSwizzle = context->priv().caps()->getReadSwizzle(format, colorType); GrSwizzle readSwizzle, writeSwizzle;
GrSwizzle writeSwizzle = context->priv().caps()->getWriteSwizzle(format, colorType); if (colorType != GrColorType::kUnknown) {
readSwizzle = context->priv().caps()->getReadSwizzle(format, colorType);
writeSwizzle = context->priv().caps()->getWriteSwizzle(format, colorType);
}
GrSurfaceProxyView readView(proxy, origin, readSwizzle); GrSurfaceProxyView readView(proxy, origin, readSwizzle);
GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle); GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle);
@ -1749,14 +1752,14 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels(
SkRect srcRectToDraw = SkRect::Make(srcRect); SkRect srcRectToDraw = SkRect::Make(srcRect);
// If the src is not texturable first try to make a copy to a texture. // If the src is not texturable first try to make a copy to a texture.
if (!texProxyView.asTextureProxy()) { if (!texProxyView.asTextureProxy()) {
texProxyView = GrSurfaceProxy::Copy(fContext, this->asSurfaceProxy(), texProxyView =
this->origin(), this->colorInfo().colorType(), GrSurfaceProxyView::Copy(fContext, texProxyView, GrMipMapped::kNo, srcRect,
GrMipMapped::kNo, srcRect, SkBackingFit::kApprox, SkBudgeted::kNo);
SkBackingFit::kApprox, SkBudgeted::kNo); if (!texProxyView) {
if (!texProxyView.asTextureProxy()) {
callback(context, nullptr); callback(context, nullptr);
return; return;
} }
SkASSERT(texProxyView.asTextureProxy());
srcRectToDraw = SkRect::MakeWH(srcRect.width(), srcRect.height()); srcRectToDraw = SkRect::MakeWH(srcRect.width(), srcRect.height());
} }
tempRTC = GrRenderTargetContext::Make( tempRTC = GrRenderTargetContext::Make(
@ -1966,14 +1969,14 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC
} else { } else {
srcView = this->readSurfaceView(); srcView = this->readSurfaceView();
if (!srcView.asTextureProxy()) { if (!srcView.asTextureProxy()) {
srcView = GrSurfaceProxy::Copy(fContext, fReadView.proxy(), this->origin(), srcView = GrSurfaceProxyView::Copy(fContext, std::move(srcView), GrMipMapped::kNo,
this->colorInfo().colorType(), GrMipMapped::kNo, srcRect, SkBackingFit::kApprox, SkBudgeted::kYes);
srcRect, SkBackingFit::kApprox, SkBudgeted::kYes); if (!srcView) {
if (!srcView.asTextureProxy()) {
// If we can't get a texture copy of the contents then give up. // If we can't get a texture copy of the contents then give up.
callback(context, nullptr); callback(context, nullptr);
return; return;
} }
SkASSERT(srcView.asTextureProxy());
x = y = 0; x = y = 0;
} }
// We assume the caller wants kPremul. There is no way to indicate a preference. // We assume the caller wants kPremul. There is no way to indicate a preference.
@ -2604,13 +2607,12 @@ bool GrRenderTargetContext::setupDstProxyView(const GrClip& clip, const GrOp& op
dstOffset = {copyRect.fLeft, copyRect.fTop}; dstOffset = {copyRect.fLeft, copyRect.fTop};
fit = SkBackingFit::kApprox; fit = SkBackingFit::kApprox;
} }
GrSurfaceProxyView newProxyView = auto copy =
GrSurfaceProxy::Copy(fContext, this->asSurfaceProxy(), this->origin(), colorType, GrSurfaceProxy::Copy(fContext, this->asSurfaceProxy(), this->origin(), GrMipMapped::kNo,
GrMipMapped::kNo, copyRect, fit, SkBudgeted::kYes, copyRect, fit, SkBudgeted::kYes, restrictions.fRectsMustMatch);
restrictions.fRectsMustMatch); SkASSERT(copy);
SkASSERT(newProxyView.proxy());
dstProxyView->setProxyView(std::move(newProxyView)); dstProxyView->setProxyView({std::move(copy), this->origin(), this->readSwizzle()});
dstProxyView->setOffset(dstOffset); dstProxyView->setOffset(dstOffset);
return true; return true;
} }

View File

@ -47,8 +47,11 @@ std::unique_ptr<GrSurfaceContext> GrSurfaceContext::Make(GrRecordingContext* con
SkASSERT(kPremul_SkAlphaType == alphaType || kOpaque_SkAlphaType == alphaType); SkASSERT(kPremul_SkAlphaType == alphaType || kOpaque_SkAlphaType == alphaType);
// Will we ever want a swizzle that is not the default write swizzle for the format and // Will we ever want a swizzle that is not the default write swizzle for the format and
// colorType here? If so we will need to manually pass that in. // colorType here? If so we will need to manually pass that in.
GrSwizzle writeSwizzle = GrSwizzle writeSwizzle;
context->priv().caps()->getWriteSwizzle(proxy->backendFormat(), colorType); if (colorType != GrColorType::kUnknown) {
writeSwizzle =
context->priv().caps()->getWriteSwizzle(proxy->backendFormat(), colorType);
}
GrSurfaceProxyView writeView(readView.refProxy(), readView.origin(), writeSwizzle); GrSurfaceProxyView writeView(readView.refProxy(), readView.origin(), writeSwizzle);
surfaceContext.reset(new GrRenderTargetContext(context, std::move(readView), surfaceContext.reset(new GrRenderTargetContext(context, std::move(readView),
std::move(writeView), colorType, std::move(writeView), colorType,
@ -74,8 +77,8 @@ std::unique_ptr<GrSurfaceContext> GrSurfaceContext::Make(GrRecordingContext* con
sk_sp<SkColorSpace> colorSpace, sk_sp<SkColorSpace> colorSpace,
SkBackingFit fit, SkBackingFit fit,
SkBudgeted budgeted) { SkBudgeted budgeted) {
GrSwizzle swizzle("rgba"); GrSwizzle swizzle;
if (!context->priv().caps()->isFormatCompressed(format)) { if (colorType != GrColorType::kUnknown && !context->priv().caps()->isFormatCompressed(format)) {
swizzle = context->priv().caps()->getReadSwizzle(format, colorType); swizzle = context->priv().caps()->getReadSwizzle(format, colorType);
} }
@ -428,7 +431,7 @@ bool GrSurfaceContext::writePixels(const GrImageInfo& origSrcInfo, const void* s
} else { } else {
SkIRect srcRect = SkIRect::MakeWH(srcInfo.width(), srcInfo.height()); SkIRect srcRect = SkIRect::MakeWH(srcInfo.width(), srcInfo.height());
SkIPoint dstPoint = SkIPoint::Make(pt.fX, pt.fY); SkIPoint dstPoint = SkIPoint::Make(pt.fX, pt.fY);
if (!this->copy(tempProxy.get(), tempOrigin, srcRect, dstPoint)) { if (!this->copy(tempProxy.get(), srcRect, dstPoint)) {
return false; return false;
} }
} }
@ -472,8 +475,7 @@ bool GrSurfaceContext::writePixels(const GrImageInfo& origSrcInfo, const void* s
srcColorType, src, rowBytes); srcColorType, src, rowBytes);
} }
bool GrSurfaceContext::copy(GrSurfaceProxy* src, GrSurfaceOrigin origin, const SkIRect& srcRect, bool GrSurfaceContext::copy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
const SkIPoint& dstPoint) {
ASSERT_SINGLE_OWNER ASSERT_SINGLE_OWNER
RETURN_FALSE_IF_ABANDONED RETURN_FALSE_IF_ABANDONED
SkDEBUGCODE(this->validate();) SkDEBUGCODE(this->validate();)
@ -483,7 +485,6 @@ bool GrSurfaceContext::copy(GrSurfaceProxy* src, GrSurfaceOrigin origin, const S
SkASSERT(src->backendFormat().textureType() != GrTextureType::kExternal); SkASSERT(src->backendFormat().textureType() != GrTextureType::kExternal);
SkASSERT(src->backendFormat() == this->asSurfaceProxy()->backendFormat()); SkASSERT(src->backendFormat() == this->asSurfaceProxy()->backendFormat());
SkASSERT(origin == this->origin());
if (this->asSurfaceProxy()->framebufferOnly()) { if (this->asSurfaceProxy()->framebufferOnly()) {
return false; return false;
@ -495,7 +496,7 @@ bool GrSurfaceContext::copy(GrSurfaceProxy* src, GrSurfaceOrigin origin, const S
// The swizzle doesn't matter for copies and it is not used. // The swizzle doesn't matter for copies and it is not used.
return this->drawingManager()->newCopyRenderTask( return this->drawingManager()->newCopyRenderTask(
GrSurfaceProxyView(sk_ref_sp(src), origin, GrSwizzle()), srcRect, GrSurfaceProxyView(sk_ref_sp(src), this->origin(), GrSwizzle("rgba")), srcRect,
this->readSurfaceView(), dstPoint); this->readSurfaceView(), dstPoint);
} }
@ -528,13 +529,11 @@ std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale(
int srcY = srcRect.fTop; int srcY = srcRect.fTop;
GrSurfaceProxyView texView = this->readSurfaceView(); GrSurfaceProxyView texView = this->readSurfaceView();
SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint; SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
GrColorType srcColorType = this->colorInfo().colorType();
SkAlphaType srcAlphaType = this->colorInfo().alphaType(); SkAlphaType srcAlphaType = this->colorInfo().alphaType();
if (!texView.asTextureProxy()) { if (!texView.asTextureProxy()) {
texView = GrSurfaceProxy::Copy(fContext, this->asSurfaceProxy(), this->origin(), texView = GrSurfaceProxyView::Copy(fContext, std::move(texView), GrMipMapped::kNo, srcRect,
srcColorType, GrMipMapped::kNo, srcRect, SkBackingFit::kApprox, SkBudgeted::kNo);
SkBackingFit::kApprox, SkBudgeted::kNo); if (!texView) {
if (!texView.proxy()) {
return nullptr; return nullptr;
} }
SkASSERT(texView.asTextureProxy()); SkASSERT(texView.asTextureProxy());
@ -737,9 +736,10 @@ GrSurfaceContext::PixelTransferResult GrSurfaceContext::transferPixels(GrColorTy
void GrSurfaceContext::validate() const { void GrSurfaceContext::validate() const {
SkASSERT(fReadView.proxy()); SkASSERT(fReadView.proxy());
fReadView.proxy()->validate(fContext); fReadView.proxy()->validate(fContext);
SkASSERT(fContext->priv().caps()->areColorTypeAndFormatCompatible( if (this->colorInfo().colorType() != GrColorType::kUnknown) {
this->colorInfo().colorType(), fReadView.proxy()->backendFormat())); SkASSERT(fContext->priv().caps()->areColorTypeAndFormatCompatible(
this->colorInfo().colorType(), fReadView.proxy()->backendFormat()));
}
this->onValidate(); this->onValidate();
} }
#endif #endif

View File

@ -65,6 +65,7 @@ public:
// make a copy (which refs the proxy) if needed. // make a copy (which refs the proxy) if needed.
GrSurfaceProxyView readSurfaceView() { return fReadView; } GrSurfaceProxyView readSurfaceView() { return fReadView; }
SkISize dimensions() const { return fReadView.dimensions(); }
int width() const { return fReadView.proxy()->width(); } int width() const { return fReadView.proxy()->width(); }
int height() const { return fReadView.proxy()->height(); } int height() const { return fReadView.proxy()->height(); }
@ -120,13 +121,12 @@ public:
const GrSurfaceContextPriv surfPriv() const; const GrSurfaceContextPriv surfPriv() const;
#if GR_TEST_UTILS #if GR_TEST_UTILS
bool testCopy(GrSurfaceProxy* src, GrSurfaceOrigin origin, const SkIRect& srcRect, bool testCopy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
const SkIPoint& dstPoint) { return this->copy(src, srcRect, dstPoint);
return this->copy(src, origin, srcRect, dstPoint);
} }
bool testCopy(GrSurfaceProxy* src, GrSurfaceOrigin origin) { bool testCopy(GrSurfaceProxy* src) {
return this->copy(src, origin, SkIRect::MakeSize(src->dimensions()), SkIPoint::Make(0, 0)); return this->copy(src, SkIRect::MakeSize(src->dimensions()), {0, 0});
} }
#endif #endif
@ -173,7 +173,6 @@ private:
* Currently only writePixels and replaceRenderTarget call this directly. All other copies * Currently only writePixels and replaceRenderTarget call this directly. All other copies
* should go through GrSurfaceProxy::Copy. * should go through GrSurfaceProxy::Copy.
* @param src src of pixels * @param src src of pixels
* @param srcRect the subset of 'src' to copy
* @param dstPoint the origin of the 'srcRect' in the destination coordinate space * @param dstPoint the origin of the 'srcRect' in the destination coordinate space
* @return true if the copy succeeded; false otherwise * @return true if the copy succeeded; false otherwise
* *
@ -183,8 +182,7 @@ private:
* regions will not be shifted. The 'src' must have the same origin as the backing proxy * regions will not be shifted. The 'src' must have the same origin as the backing proxy
* of fSurfaceContext. * of fSurfaceContext.
*/ */
bool copy(GrSurfaceProxy* src, GrSurfaceOrigin origin, const SkIRect& srcRect, bool copy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint);
const SkIPoint& dstPoint);
GrColorInfo fColorInfo; GrColorInfo fColorInfo;

View File

@ -264,15 +264,14 @@ void GrSurfaceProxy::validate(GrContext_Base* context) const {
} }
#endif #endif
GrSurfaceProxyView GrSurfaceProxy::Copy(GrRecordingContext* context, sk_sp<GrSurfaceProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
GrSurfaceProxy* src, GrSurfaceProxy* src,
GrSurfaceOrigin origin, GrSurfaceOrigin origin,
GrColorType srcColorType, GrMipMapped mipMapped,
GrMipMapped mipMapped, SkIRect srcRect,
SkIRect srcRect, SkBackingFit fit,
SkBackingFit fit, SkBudgeted budgeted,
SkBudgeted budgeted, RectsMustMatch rectsMustMatch) {
RectsMustMatch rectsMustMatch) {
SkASSERT(!src->isFullyLazy()); SkASSERT(!src->isFullyLazy());
int width; int width;
int height; int height;
@ -295,37 +294,36 @@ GrSurfaceProxyView GrSurfaceProxy::Copy(GrRecordingContext* context,
SkASSERT(format.isValid()); SkASSERT(format.isValid());
if (src->backendFormat().textureType() != GrTextureType::kExternal) { if (src->backendFormat().textureType() != GrTextureType::kExternal) {
auto dstContext = GrSurfaceContext::Make(context, {width, height}, format, auto dstContext =
GrRenderable::kNo, 1, mipMapped, GrSurfaceContext::Make(context, {width, height}, format, GrRenderable::kNo, 1,
src->isProtected(), origin, srcColorType, mipMapped, src->isProtected(), origin, GrColorType::kUnknown,
kUnknown_SkAlphaType, nullptr, fit, budgeted); kUnknown_SkAlphaType, nullptr, fit, budgeted);
if (dstContext && dstContext->copy(src, origin, srcRect, dstPoint)) { if (dstContext && dstContext->copy(src, srcRect, dstPoint)) {
return dstContext->readSurfaceView(); return dstContext->asSurfaceProxyRef();
} }
} }
if (src->asTextureProxy()) { if (src->asTextureProxy()) {
auto dstContext = GrRenderTargetContext::Make(context, srcColorType, nullptr, fit, auto dstContext = GrRenderTargetContext::Make(
{width, height}, format, 1, context, GrColorType::kUnknown, nullptr, fit, {width, height}, format, 1, mipMapped,
mipMapped, src->isProtected(), origin, src->isProtected(), origin, budgeted, nullptr);
budgeted, nullptr); GrSurfaceProxyView view(sk_ref_sp(src), origin, GrSwizzle("rgba"));
GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(src->backendFormat(),
srcColorType);
GrSurfaceProxyView view(sk_ref_sp(src), origin, swizzle);
if (dstContext && dstContext->blitTexture(std::move(view), srcRect, dstPoint)) { if (dstContext && dstContext->blitTexture(std::move(view), srcRect, dstPoint)) {
return dstContext->readSurfaceView(); return dstContext->asSurfaceProxyRef();
} }
} }
// Can't use backend copies or draws. // Can't use backend copies or draws.
return {}; return nullptr;
} }
GrSurfaceProxyView GrSurfaceProxy::Copy(GrRecordingContext* context, GrSurfaceProxy* src, sk_sp<GrSurfaceProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
GrSurfaceOrigin origin, GrColorType srcColorType, GrSurfaceProxy* src,
GrMipMapped mipMapped, SkBackingFit fit, GrSurfaceOrigin origin,
SkBudgeted budgeted) { GrMipMapped mipMapped,
SkBackingFit fit,
SkBudgeted budgeted) {
SkASSERT(!src->isFullyLazy()); SkASSERT(!src->isFullyLazy());
return Copy(context, src, origin, srcColorType, mipMapped, SkIRect::MakeSize(src->dimensions()), return Copy(context, src, origin, mipMapped, SkIRect::MakeSize(src->dimensions()), fit,
fit, budgeted); budgeted);
} }
#if GR_TEST_UTILS #if GR_TEST_UTILS

View File

@ -285,23 +285,25 @@ public:
// The copy is is not a render target and not multisampled. // The copy is is not a render target and not multisampled.
// //
// The intended use of this copy call is simply to copy exact pixel values from one proxy to a // The intended use of this copy call is simply to copy exact pixel values from one proxy to a
// new one. Thus there isn't a need for a swizzle when doing the copy. Also, there shouldn't be // new one. Thus, there isn't a need for a swizzle when doing the copy. The format of the copy
// an assumed "view" of the copy. However, even though not really needed for the swizzle, we // will be the same as the src. Therefore, the copy can be used in a view with the same swizzle
// still pass in a srcColorType since it is required for making a GrSurface/RenderTargetContext. // as the original for use with a given color type.
// Additionally, almost all callers of this will immediately put the resulting proxy into a view static sk_sp<GrSurfaceProxy> Copy(GrRecordingContext*,
// which is compatible with the srcColorType and origin passed in here. Thus for now we just GrSurfaceProxy* src,
// return the GrSurfaceProxyView that is already stored on the internal GrSurfaceContext. If we GrSurfaceOrigin,
// later decide to not pass in a srcColorType (and assume some default color type based on the GrMipMapped,
// backend format) then we should go back to returning a proxy here and have the callers decide SkIRect srcRect,
// what view they want of the proxy. SkBackingFit,
static GrSurfaceProxyView Copy(GrRecordingContext*, GrSurfaceProxy* src, SkBudgeted,
GrSurfaceOrigin, GrColorType srcColorType, GrMipMapped, RectsMustMatch = RectsMustMatch::kNo);
SkIRect srcRect, SkBackingFit, SkBudgeted,
RectsMustMatch = RectsMustMatch::kNo);
// Same as above Copy but copies the entire 'src' // Same as above Copy but copies the entire 'src'
static GrSurfaceProxyView Copy(GrRecordingContext*, GrSurfaceProxy* src, GrSurfaceOrigin, static sk_sp<GrSurfaceProxy> Copy(GrRecordingContext*,
GrColorType srcColorType, GrMipMapped, SkBackingFit, SkBudgeted); GrSurfaceProxy* src,
GrSurfaceOrigin,
GrMipMapped,
SkBackingFit,
SkBudgeted);
#if GR_TEST_UTILS #if GR_TEST_UTILS
int32_t testingOnly_getBackingRefCnt() const; int32_t testingOnly_getBackingRefCnt() const;

View File

@ -76,6 +76,20 @@ public:
*this = {}; *this = {};
} }
// Helper that copies a rect of a src view'' proxy and then creates a view for the copy with
// the same origin and swizzle as the src view.
static GrSurfaceProxyView Copy(GrRecordingContext* context,
GrSurfaceProxyView src,
GrMipMapped mipMapped,
SkIRect srcRect,
SkBackingFit fit,
SkBudgeted budgeted) {
auto origin = src.origin();
auto* proxy = src.proxy();
auto copy = GrSurfaceProxy::Copy(context, proxy, origin, mipMapped, srcRect, fit, budgeted);
return {std::move(copy), src.origin(), src.swizzle()};
}
// This does not reset the origin or swizzle, so the View can still be used to access those // This does not reset the origin or swizzle, so the View can still be used to access those
// properties associated with the detached proxy. // properties associated with the detached proxy.
sk_sp<GrSurfaceProxy> detachProxy() { sk_sp<GrSurfaceProxy> detachProxy() {

View File

@ -38,17 +38,15 @@ GrSurfaceProxyView GrTextureAdjuster::makeMippedCopy() {
} }
} }
GrSurfaceProxyView copyView = GrCopyBaseMipMapToTextureProxy( auto copy = GrCopyBaseMipMapToView(this->context(), fOriginal);
this->context(), fOriginal.proxy(), fOriginal.origin(), this->colorType()); if (!copy) {
if (!copyView) {
return {}; return {};
} }
if (mipMappedKey.isValid()) { if (mipMappedKey.isValid()) {
SkASSERT(copyView.origin() == fOriginal.origin());
// TODO: If we move listeners up from SkImage_Lazy to SkImage_Base then add one here. // TODO: If we move listeners up from SkImage_Lazy to SkImage_Base then add one here.
proxyProvider->assignUniqueKeyToProxy(mipMappedKey, copyView.asTextureProxy()); proxyProvider->assignUniqueKeyToProxy(mipMappedKey, copy.asTextureProxy());
} }
return copyView; return copy;
} }
GrSurfaceProxyView GrTextureAdjuster::onView(GrMipMapped mipMapped) { GrSurfaceProxyView GrTextureAdjuster::onView(GrMipMapped mipMapped) {

View File

@ -806,21 +806,18 @@ sk_sp<SkSpecialImage> SkGpuDevice::snapSpecial(const SkIRect& subset, bool force
if (forceCopy || !view.asTextureProxy()) { if (forceCopy || !view.asTextureProxy()) {
// When the device doesn't have a texture, or a copy is requested, we create a temporary // When the device doesn't have a texture, or a copy is requested, we create a temporary
// texture that matches the device contents // texture that matches the device contents
view = GrSurfaceProxy::Copy(fContext.get(), view = GrSurfaceProxyView::Copy(fContext.get(),
rtc->asSurfaceProxy(), std::move(view),
view.origin(), GrMipMapped::kNo, // Don't auto generate mips
rtc->colorInfo().colorType(), subset,
GrMipMapped::kNo, // Don't auto generate mips SkBackingFit::kApprox,
subset, SkBudgeted::kYes); // Always budgeted
SkBackingFit::kApprox,
SkBudgeted::kYes); // Always budgeted
if (!view) { if (!view) {
return nullptr; return nullptr;
} }
// Since this copied only the requested subset, the special image wrapping the proxy no // Since this copied only the requested subset, the special image wrapping the proxy no
// longer needs the original subset. // longer needs the original subset.
finalSubset = SkIRect::MakeSize(view.proxy()->dimensions()); finalSubset = SkIRect::MakeSize(view.dimensions());
} }
GrColorType ct = SkColorTypeToGrColorType(this->imageInfo().colorType()); GrColorType ct = SkColorTypeToGrColorType(this->imageInfo().colorType());

View File

@ -131,25 +131,31 @@ sk_sp<SkIDChangeListener> GrMakeUniqueKeyInvalidationListener(GrUniqueKey* key,
return std::move(listener); return std::move(listener);
} }
GrSurfaceProxyView GrCopyBaseMipMapToTextureProxy(GrRecordingContext* ctx, sk_sp<GrSurfaceProxy> GrCopyBaseMipMapToTextureProxy(GrRecordingContext* ctx,
GrSurfaceProxy* baseProxy, GrSurfaceProxy* baseProxy,
GrSurfaceOrigin origin, GrSurfaceOrigin origin,
GrColorType srcColorType, SkBudgeted budgeted) {
SkBudgeted budgeted) {
SkASSERT(baseProxy); SkASSERT(baseProxy);
if (!ctx->priv().caps()->isFormatCopyable(baseProxy->backendFormat())) { if (!ctx->priv().caps()->isFormatCopyable(baseProxy->backendFormat())) {
return {}; return {};
} }
GrSurfaceProxyView view = GrSurfaceProxy::Copy(ctx, auto copy = GrSurfaceProxy::Copy(ctx, baseProxy, origin, GrMipMapped::kYes,
baseProxy, SkBackingFit::kExact, budgeted);
origin, if (!copy) {
srcColorType, return {};
GrMipMapped::kYes, }
SkBackingFit::kExact, SkASSERT(copy->asTextureProxy());
budgeted); return copy;
SkASSERT(!view.proxy() || view.asTextureProxy()); }
return view;
GrSurfaceProxyView GrCopyBaseMipMapToView(GrRecordingContext* context,
GrSurfaceProxyView src,
SkBudgeted budgeted) {
auto origin = src.origin();
auto swizzle = src.swizzle();
auto* proxy = src.proxy();
return {GrCopyBaseMipMapToTextureProxy(context, proxy, origin, budgeted), origin, swizzle};
} }
GrSurfaceProxyView GrRefCachedBitmapView(GrRecordingContext* ctx, const SkBitmap& bitmap, GrSurfaceProxyView GrRefCachedBitmapView(GrRecordingContext* ctx, const SkBitmap& bitmap,

View File

@ -171,11 +171,17 @@ GrSurfaceProxyView GrRefCachedBitmapView(GrRecordingContext*, const SkBitmap&, G
/** /**
* Creates a new texture with mipmap levels and copies the baseProxy into the base layer. * Creates a new texture with mipmap levels and copies the baseProxy into the base layer.
*/ */
GrSurfaceProxyView GrCopyBaseMipMapToTextureProxy(GrRecordingContext*, sk_sp<GrSurfaceProxy> GrCopyBaseMipMapToTextureProxy(GrRecordingContext*,
GrSurfaceProxy* baseProxy, GrSurfaceProxy* baseProxy,
GrSurfaceOrigin origin, GrSurfaceOrigin origin,
GrColorType srcColorType, SkBudgeted = SkBudgeted::kYes);
SkBudgeted = SkBudgeted::kYes); /**
* Same as GrCopyBaseMipMapToTextureProxy but takes the src as a view and returns a view with same
* origin and swizzle as the src view.
*/
GrSurfaceProxyView GrCopyBaseMipMapToView(GrRecordingContext*,
GrSurfaceProxyView,
SkBudgeted = SkBudgeted::kYes);
/* /*
* Create a texture proxy from the provided bitmap and add it to the texture cache * Create a texture proxy from the provided bitmap and add it to the texture cache

View File

@ -437,15 +437,11 @@ sk_sp<SkImage> SkImage::makeTextureImage(GrContext* context,
!context->priv().caps()->mipMapSupport()) { !context->priv().caps()->mipMapSupport()) {
return sk_ref_sp(const_cast<SkImage*>(this)); return sk_ref_sp(const_cast<SkImage*>(this));
} }
auto copy = GrCopyBaseMipMapToTextureProxy(context->priv().asRecordingContext(), auto copy = GrCopyBaseMipMapToView(context->priv().asRecordingContext(), *view, budgeted);
view->proxy(),
view->origin(),
SkColorTypeToGrColorType(this->colorType()),
budgeted);
if (!copy) { if (!copy) {
return nullptr; return nullptr;
} }
return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), this->uniqueID(), std::move(copy), return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), this->uniqueID(), copy,
this->colorType(), this->alphaType(), this->refColorSpace()); this->colorType(), this->alphaType(), this->refColorSpace());
} }

View File

@ -143,13 +143,10 @@ sk_sp<SkImage> SkImage_GpuBase::onMakeSubset(GrRecordingContext* context,
const GrSurfaceProxyView* view = this->view(context); const GrSurfaceProxyView* view = this->view(context);
SkASSERT(view && view->proxy()); SkASSERT(view && view->proxy());
GrColorType grColorType = SkColorTypeToGrColorType(this->colorType()); auto copyView = GrSurfaceProxyView::Copy(context, *view, GrMipMapped::kNo, subset,
SkBackingFit::kExact, view->proxy()->isBudgeted());
GrSurfaceProxyView copyView = GrSurfaceProxy::Copy( if (!copyView) {
context, view->proxy(), view->origin(), grColorType, GrMipMapped::kNo, subset,
SkBackingFit::kExact, view->proxy()->isBudgeted());
if (!copyView.proxy()) {
return nullptr; return nullptr;
} }

View File

@ -97,9 +97,8 @@ bool SkImage_GpuYUVA::setupMipmapsForPlanes(GrRecordingContext* context) const {
if (mipCount && GrGpu::IsACopyNeededForMips(fContext->priv().caps(), if (mipCount && GrGpu::IsACopyNeededForMips(fContext->priv().caps(),
fViews[i].asTextureProxy(), fViews[i].asTextureProxy(),
GrSamplerState::Filter::kMipMap)) { GrSamplerState::Filter::kMipMap)) {
auto mippedView = GrCopyBaseMipMapToTextureProxy(context, fViews[i].asTextureProxy(), auto mippedView = GrCopyBaseMipMapToView(context, fViews[i]);
fOrigin, fProxyColorTypes[i]); if (!mippedView) {
if (!mippedView.proxy()) {
return false; return false;
} }
fViews[i] = std::move(mippedView); fViews[i] = std::move(mippedView);
@ -174,16 +173,13 @@ GrSurfaceProxyView SkImage_GpuYUVA::refMippedView(GrRecordingContext* context) c
} }
// need to generate mips for the proxy // need to generate mips for the proxy
GrColorType srcColorType = SkColorTypeToGrColorType(this->colorType()); auto mippedView = GrCopyBaseMipMapToView(context, fRGBView);
GrSurfaceProxyView mippedView = GrCopyBaseMipMapToTextureProxy(context, fRGBView.proxy(), if (!mippedView) {
fRGBView.origin(), srcColorType); return {};
if (mippedView) {
fRGBView = std::move(mippedView);
return fRGBView;
} }
// failed to generate mips fRGBView = std::move(mippedView);
return {}; return fRGBView;
} }
const GrSurfaceProxyView* SkImage_GpuYUVA::view(GrRecordingContext* context) const { const GrSurfaceProxyView* SkImage_GpuYUVA::view(GrRecordingContext* context) const {

View File

@ -435,17 +435,16 @@ GrSurfaceProxyView SkImage_Lazy::lockTextureProxyView(GrRecordingContext* ctx,
// We need a mipped proxy, but we found a cached proxy that wasn't mipped. Thus we // We need a mipped proxy, but we found a cached proxy that wasn't mipped. Thus we
// generate a new mipped surface and copy the original proxy into the base layer. We // generate a new mipped surface and copy the original proxy into the base layer. We
// will then let the gpu generate the rest of the mips. // will then let the gpu generate the rest of the mips.
GrSurfaceProxyView mippedView = GrCopyBaseMipMapToTextureProxy( auto mippedView = GrCopyBaseMipMapToView(ctx, view);
ctx, view.proxy(), kTopLeft_GrSurfaceOrigin, ct); if (!mippedView) {
if (mippedView) { // We failed to make a mipped proxy with the base copied into it. This could
proxyProvider->removeUniqueKeyFromProxy(view.asTextureProxy()); // have been from failure to make the proxy or failure to do the copy. Thus we
installKey(mippedView); // will fall back to just using the non mipped proxy; See skbug.com/7094.
return mippedView; return view;
} }
// We failed to make a mipped proxy with the base copied into it. This could have proxyProvider->removeUniqueKeyFromProxy(view.asTextureProxy());
// been from failure to make the proxy or failure to do the copy. Thus we will fall installKey(mippedView);
// back to just using the non mipped proxy; See skbug.com/7094. return mippedView;
return view;
} }
} }
} }

View File

@ -101,20 +101,14 @@ sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot(const SkIRect* subset) {
SkBudgeted budgeted = rtc->asSurfaceProxy()->isBudgeted(); SkBudgeted budgeted = rtc->asSurfaceProxy()->isBudgeted();
GrSurfaceProxyView srcView; GrSurfaceProxyView srcView = rtc->readSurfaceView();
if (subset) { if (subset || !srcView.asTextureProxy() || rtc->priv().refsWrappedObjects()) {
srcView = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->origin(),
rtc->colorInfo().colorType(), rtc->mipMapped(), *subset,
SkBackingFit::kExact, budgeted);
} else if (!rtc->asTextureProxy() || rtc->priv().refsWrappedObjects()) {
// If the original render target is a buffer originally created by the client, then we don't // If the original render target is a buffer originally created by the client, then we don't
// want to ever retarget the SkSurface at another buffer we create. Force a copy now to // want to ever retarget the SkSurface at another buffer we create. Force a copy now to
// avoid copy-on-write. // avoid copy-on-write.
srcView = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->origin(), auto rect = subset ? *subset : SkIRect::MakeSize(rtc->dimensions());
rtc->colorInfo().colorType(), rtc->mipMapped(), srcView = GrSurfaceProxyView::Copy(ctx, std::move(srcView), rtc->mipMapped(), rect,
SkBackingFit::kExact, budgeted); SkBackingFit::kExact, budgeted);
} else {
srcView = rtc->readSurfaceView();
} }
const SkImageInfo info = fDevice->imageInfo(); const SkImageInfo info = fDevice->imageInfo();

View File

@ -115,8 +115,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CopySurface, reporter, ctxInfo) {
bool result = false; bool result = false;
if (sOrigin == dOrigin) { if (sOrigin == dOrigin) {
result = dstContext->testCopy(src.get(), sOrigin, srcRect, result = dstContext->testCopy(src.get(), srcRect, dstPoint);
dstPoint);
} else if (dRenderable == GrRenderable::kYes) { } else if (dRenderable == GrRenderable::kYes) {
SkASSERT(dstContext->asRenderTargetContext()); SkASSERT(dstContext->asRenderTargetContext());
GrSwizzle srcSwizzle = context->priv().caps()->getReadSwizzle( GrSwizzle srcSwizzle = context->priv().caps()->getReadSwizzle(

View File

@ -402,7 +402,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadOnlyTexture, reporter, context_info) {
auto copySrc = maker.view(GrMipMapped::kNo); auto copySrc = maker.view(GrMipMapped::kNo);
REPORTER_ASSERT(reporter, copySrc.proxy()); REPORTER_ASSERT(reporter, copySrc.proxy());
auto copyResult = surfContext->testCopy(copySrc.proxy(), copySrc.origin()); auto copyResult = surfContext->testCopy(copySrc.proxy());
REPORTER_ASSERT(reporter, copyResult == (ioType == kRW_GrIOType)); REPORTER_ASSERT(reporter, copyResult == (ioType == kRW_GrIOType));
// Try the low level copy. // Try the low level copy.
context->flush(); context->flush();
@ -792,7 +792,7 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(TextureIdleStateTest, reporter, contextInfo) {
auto proxy = auto proxy =
context->priv().proxyProvider()->testingOnly_createWrapped(std::move(idleTexture)); context->priv().proxyProvider()->testingOnly_createWrapped(std::move(idleTexture));
context->flush(); context->flush();
SkAssertResult(rtc->testCopy(proxy.get(), rtc->origin())); SkAssertResult(rtc->testCopy(proxy.get()));
proxy.reset(); proxy.reset();
REPORTER_ASSERT(reporter, flags == 0); REPORTER_ASSERT(reporter, flags == 0);

View File

@ -43,16 +43,16 @@ DEF_GPUTEST_FOR_METAL_CONTEXT(MtlCopySurfaceTest, reporter, ctxInfo) {
GrProxyProvider* proxyProvider = context->priv().proxyProvider(); GrProxyProvider* proxyProvider = context->priv().proxyProvider();
sk_sp<GrSurfaceProxy> srcProxy = proxyProvider->wrapBackendRenderTarget(backendRT); sk_sp<GrSurfaceProxy> srcProxy = proxyProvider->wrapBackendRenderTarget(backendRT);
GrSurfaceProxyView dstView = GrSurfaceProxy::Copy(context, srcProxy.get(), auto dstProxy = GrSurfaceProxy::Copy(context,
kTopLeft_GrSurfaceOrigin, srcProxy.get(),
GrColorType::kBGRA_8888, kTopLeft_GrSurfaceOrigin,
GrMipMapped::kNo, GrMipMapped::kNo,
SkBackingFit::kExact, SkBackingFit::kExact,
SkBudgeted::kYes); SkBudgeted::kYes);
// TODO: GrSurfaceProxy::Copy doesn't check to see if the framebufferOnly bit is set yet. // TODO: GrSurfaceProxy::Copy doesn't check to see if the framebufferOnly bit is set yet.
// Update this when it does -- it should fail. // Update this when it does -- it should fail.
if (!dstView.proxy()) { if (!dstProxy) {
ERRORF(reporter, "Expected copy to succeed"); ERRORF(reporter, "Expected copy to succeed");
} }

View File

@ -116,7 +116,7 @@ static void test_copy_to_surface(skiatest::Reporter* reporter,
pixels.get(), 0); pixels.get(), 0);
// If this assert ever fails we can add a fallback to do copy as draw, but until then we can // If this assert ever fails we can add a fallback to do copy as draw, but until then we can
// be more restrictive. // be more restrictive.
SkAssertResult(dstContext->testCopy(src.get(), origin)); SkAssertResult(dstContext->testCopy(src.get()));
TestReadPixels(reporter, dstContext, pixels.get(), testName); TestReadPixels(reporter, dstContext, pixels.get(), testName);
} }
} }

View File

@ -81,11 +81,11 @@ void TestCopyFromSurface(skiatest::Reporter* reporter,
GrColorType colorType, GrColorType colorType,
uint32_t expectedPixelValues[], uint32_t expectedPixelValues[],
const char* testName) { const char* testName) {
GrSurfaceProxyView view = GrSurfaceProxy::Copy(context, proxy, origin, colorType, auto copy = GrSurfaceProxy::Copy(context, proxy, origin, GrMipMapped::kNo, SkBackingFit::kExact,
GrMipMapped::kNo, SkBackingFit::kExact, SkBudgeted::kYes);
SkBudgeted::kYes); SkASSERT(copy && copy->asTextureProxy());
SkASSERT(view.asTextureProxy()); auto swizzle = context->priv().caps()->getReadSwizzle(copy->backendFormat(), colorType);
GrSurfaceProxyView view(std::move(copy), origin, swizzle);
auto dstContext = GrSurfaceContext::Make(context, std::move(view), colorType, auto dstContext = GrSurfaceContext::Make(context, std::move(view), colorType,
kPremul_SkAlphaType, nullptr); kPremul_SkAlphaType, nullptr);
SkASSERT(dstContext); SkASSERT(dstContext);