From 4d03689edb5dfdce22f11414d2351ce2b221a410 Mon Sep 17 00:00:00 2001 From: Brian Salomon Date: Tue, 2 Jul 2019 15:10:58 -0400 Subject: [PATCH] Make GrRenderTargetContext async read functions use GrRTC's alpha type. This shouldn't have any practical effect since GrRTC can't be unpremul but removes assumptions in these functions. This code will eventually be lifted up to GrSurfaceContext which can be unpremul. Change-Id: If8b2fb8b19d1160bc6561f6536518563f57c4351 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/225185 Reviewed-by: Robert Phillips Commit-Queue: Brian Salomon --- src/gpu/GrRenderTargetContext.cpp | 73 ++++++++++++++++--------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 352d3c6fb0..b85de5c6f3 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -1652,10 +1652,8 @@ sk_sp GrRenderTargetContext::rescale(const SkImageInfo& i return nullptr; } - // We currently don't know our own alpha type, we assume it's premul if we have an alpha channel - // and opaque otherwise. - if (!GrPixelConfigIsAlphaOnly(fRenderTargetProxy->config()) && - info.alphaType() != kPremul_SkAlphaType) { + // We rescale by drawing and don't currently support drawing to a kUnpremul destination. + if (info.alphaType() == kUnpremul_SkAlphaType) { return nullptr; } @@ -1692,17 +1690,17 @@ sk_sp GrRenderTargetContext::rescale(const SkImageInfo& i stepsY = sy != 1.f; } SkASSERT(stepsX || stepsY); - auto rescaleColorSapce = this->colorSpaceInfo().refColorSpace(); auto currRTC = sk_ref_sp(this); // Assume we should ignore the rescale linear request if the surface has no color space since // it's unclear how we'd linearize from an unknown color space. - if (rescaleGamma == SkSurface::RescaleGamma::kLinear && - rescaleColorSapce.get() && !rescaleColorSapce->gammaIsLinear()) { - auto cs = rescaleColorSapce->makeLinearGamma(); + if (rescaleGamma == SkSurface::RescaleGamma::kLinear && this->colorSpaceInfo().colorSpace() && + !this->colorSpaceInfo().colorSpace()->gammaIsLinear()) { + auto cs = this->colorSpaceInfo().colorSpace()->makeLinearGamma(); auto backendFormat = this->caps()->getBackendFormatFromGrColorType(GrColorType::kRGBA_F16, GrSRGBEncoded::kNo); - auto xform = GrColorSpaceXform::Make(rescaleColorSapce.get(), kPremul_SkAlphaType, cs.get(), - kPremul_SkAlphaType); + auto xform = GrColorSpaceXform::Make(this->colorSpaceInfo().colorSpace(), + this->colorSpaceInfo().alphaType(), + cs.get(), kPremul_SkAlphaType); // We'll fall back to kRGBA_8888 if half float not supported. auto linearRTC = fContext->priv().makeDeferredRenderTargetContextWithFallback( backendFormat, SkBackingFit::kExact, srcW, srcH, kRGBA_half_GrPixelConfig, @@ -1717,7 +1715,6 @@ sk_sp GrRenderTargetContext::rescale(const SkImageInfo& i std::move(xform)); texProxy = linearRTC->asTextureProxyRef(); currRTC = std::move(linearRTC); - rescaleColorSapce = std::move(cs); srcX = 0; srcY = 0; constraint = SkCanvas::kFast_SrcRectConstraint; @@ -1746,16 +1743,18 @@ sk_sp GrRenderTargetContext::rescale(const SkImageInfo& i GrBackendFormat backendFormat = texProxy->backendFormat().makeTexture2D(); GrPixelConfig config = texProxy->config(); GrColorType colorType = currRTC->colorSpaceInfo().colorType(); - auto cs = rescaleColorSapce; + auto cs = currRTC->colorSpaceInfo().refColorSpace(); sk_sp xform; + auto prevAlphaType = currRTC->colorSpaceInfo().alphaType(); if (!stepsX && !stepsY) { // Might as well fold conversion to final info in the last step. backendFormat = this->caps()->getBackendFormatFromColorType(info.colorType()); config = this->caps()->getConfigFromBackendFormat(backendFormat, info.colorType()); cs = info.refColorSpace(); colorType = SkColorTypeToGrColorType(info.colorType()); - xform = GrColorSpaceXform::Make(rescaleColorSapce.get(), - kPremul_SkAlphaType, cs.get(), info.alphaType()); + xform = GrColorSpaceXform::Make(currRTC->colorSpaceInfo().colorSpace(), + currRTC->colorSpaceInfo().alphaType(), + cs.get(), info.alphaType()); } currRTC = fContext->priv().makeDeferredRenderTargetContextWithFallback( backendFormat, SkBackingFit::kExact, nextW, nextH, config, colorType, std::move(cs), @@ -1777,9 +1776,9 @@ sk_sp GrRenderTargetContext::rescale(const SkImageInfo& i if (srcW != texProxy->width() || srcH != texProxy->height()) { auto domain = GrTextureDomain::MakeTexelDomain( SkIRect::MakeXYWH(srcX, srcY, srcW, srcH), GrTextureDomain::kClamp_Mode); - fp = GrBicubicEffect::Make(texProxy, matrix, domain, dir, kPremul_SkAlphaType); + fp = GrBicubicEffect::Make(texProxy, matrix, domain, dir, prevAlphaType); } else { - fp = GrBicubicEffect::Make(texProxy, matrix, dir, kPremul_SkAlphaType); + fp = GrBicubicEffect::Make(texProxy, matrix, dir, prevAlphaType); } if (xform) { fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(xform)); @@ -1819,13 +1818,6 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels( callback(context, nullptr, 0); return; } - // We currently don't know our own alpha type, we assume it's premul if we have an alpha channel - // and opaque otherwise. - if (!GrPixelConfigIsAlphaOnly(fRenderTargetProxy->config()) && - info.alphaType() != kPremul_SkAlphaType) { - callback(context, nullptr, 0); - return; - } auto dstCT = SkColorTypeToGrColorType(info.colorType()); bool needsRescale = srcRect.width() != info.width() || srcRect.height() != info.height(); GrPixelConfig configOfFinalContext = fRenderTargetProxy->config(); @@ -1866,10 +1858,17 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels( x = y = 0; } else { sk_sp xform = - GrColorSpaceXform::Make(this->colorSpaceInfo().colorSpace(), kPremul_SkAlphaType, + GrColorSpaceXform::Make(this->colorSpaceInfo().colorSpace(), + this->colorSpaceInfo().alphaType(), info.colorSpace(), info.alphaType()); // Insert a draw to a temporary surface if we need to do a y-flip or color space conversion. if (this->origin() == kBottomLeft_GrSurfaceOrigin || xform) { + // We flip or color convert by drawing and we don't currently support drawing to + // kPremul. + if (info.alphaType() == kUnpremul_SkAlphaType) { + callback(context, nullptr, 0); + return; + } sk_sp texProxy = sk_ref_sp(fRenderTargetProxy->asTextureProxy()); const auto backendFormat = fRenderTargetProxy->backendFormat().makeTexture2D(); SkRect srcRectToDraw = SkRect::Make(srcRect); @@ -1953,6 +1952,8 @@ GrRenderTargetContext::PixelTransferResult GrRenderTargetContext::transferPixels if (supportedRead.fColorType != dstCT || supportedRead.fSwizzle != GrSwizzle("rgba") || flip) { result.fPixelConverter = [w = rect.width(), h = rect.height(), dstCT, supportedRead]( void* dst, const void* src) { + // We're using kPremul here for src and dst simply because we don't want any alpha type + // conversions. GrPixelInfo srcInfo(supportedRead.fColorType, kPremul_SkAlphaType, nullptr, w, h); GrPixelInfo dstInfo(dstCT, kPremul_SkAlphaType, nullptr, w, h); GrConvertPixels(dstInfo, dst, dstInfo.minRowBytes(), @@ -1973,7 +1974,8 @@ void GrRenderTargetContext::asyncReadPixels(const SkIRect& rect, SkColorType col if (!transferResult.fTransferBuffer) { SkAutoPixmapStorage pm; - auto ii = SkImageInfo::Make(rect.width(), rect.height(), colorType, kPremul_SkAlphaType, + auto ii = SkImageInfo::Make(rect.width(), rect.height(), colorType, + this->colorSpaceInfo().alphaType(), this->colorSpaceInfo().refColorSpace()); pm.alloc(ii); if (!this->readPixels(ii, pm.writable_addr(), pm.rowBytes(), {rect.fLeft, rect.fTop})) { @@ -2003,15 +2005,14 @@ void GrRenderTargetContext::asyncReadPixels(const SkIRect& rect, SkColorType col delete context; return; } - SkAutoPixmapStorage pm; + std::unique_ptr tmp; + size_t rowBytes = context->fW * SkColorTypeBytesPerPixel(context->fColorType); if (context->fTransferResult.fPixelConverter) { - pm.alloc(SkImageInfo::Make(context->fW, context->fH, context->fColorType, - kPremul_SkAlphaType, nullptr)); - context->fTransferResult.fPixelConverter(pm.writable_addr(), data); - data = pm.addr(); + tmp.reset(new char[rowBytes * context->fH]); + context->fTransferResult.fPixelConverter(tmp.get(), data); + data = tmp.get(); } - (*context->fClientCallback)(context->fClientContext, data, - context->fW * SkColorTypeBytesPerPixel(context->fColorType)); + (*context->fClientCallback)(context->fClientContext, data, rowBytes); delete context; }; GrFlushInfo flushInfo; @@ -2044,6 +2045,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420( auto rtc = sk_ref_sp(this); bool needsRescale = srcRect.width() != dstW || srcRect.height() != dstH; if (needsRescale) { + // We assume the caller wants kPremul. There is no way to indicate a preference. auto info = SkImageInfo::Make(dstW, dstH, kRGBA_8888_SkColorType, kPremul_SkAlphaType, dstColorSpace); // TODO: Incorporate the YUV conversion into last pass of rescaling. @@ -2056,9 +2058,10 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420( SkASSERT(rtc->origin() == kTopLeft_GrSurfaceOrigin); x = y = 0; } else { - sk_sp xform = - GrColorSpaceXform::Make(this->colorSpaceInfo().colorSpace(), kPremul_SkAlphaType, - dstColorSpace.get(), kPremul_SkAlphaType); + // We assume the caller wants kPremul. There is no way to indicate a preference. + sk_sp xform = GrColorSpaceXform::Make( + this->colorSpaceInfo().colorSpace(), this->colorSpaceInfo().alphaType(), + dstColorSpace.get(), kPremul_SkAlphaType); if (xform) { sk_sp texProxy = this->asTextureProxyRef(); // TODO: Do something if the input is not a texture already.