From d494f6e3d68269d1a60e864561aa66a7b125be1a Mon Sep 17 00:00:00 2001 From: Brian Salomon Date: Fri, 1 Jun 2018 14:13:43 -0400 Subject: Replace GrContextPriv::read/writeSurfacePixels with GrContextPriv::read/WritePixels2 Change-Id: I08be0f347d360e97bf9a6d1aeb25f9f584cc3d89 Reviewed-on: https://skia-review.googlesource.com/131442 Commit-Queue: Brian Salomon Commit-Queue: Brian Osman Auto-Submit: Brian Salomon Reviewed-by: Brian Osman --- src/gpu/GrContext.cpp | 449 ++--------------------------------------------- src/gpu/GrContextPriv.h | 14 +- src/gpu/GrGpu.cpp | 84 --------- src/gpu/GrGpu.h | 40 ----- src/gpu/gl/GrGLGpu.cpp | 132 -------------- src/gpu/gl/GrGLGpu.h | 3 - src/gpu/mock/GrMockGpu.h | 5 - src/gpu/mtl/GrMtlGpu.h | 6 - src/gpu/vk/GrVkGpu.cpp | 33 ---- src/gpu/vk/GrVkGpu.h | 3 - 10 files changed, 13 insertions(+), 756 deletions(-) diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index b020729f67..d670319c7d 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -375,22 +375,6 @@ void GrContextPriv::flush(GrSurfaceProxy* proxy) { fContext->fDrawingManager->flush(proxy); } -bool sw_convert_to_premul(GrColorType srcColorType, int width, int height, size_t inRowBytes, - const void* inPixels, size_t outRowBytes, void* outPixels) { - SkColorType colorType = GrColorTypeToSkColorType(srcColorType); - if (kUnknown_SkColorType == colorType || 4 != SkColorTypeBytesPerPixel(colorType)) { - return false; - } - - for (int y = 0; y < height; y++) { - SkOpts::RGBA_to_rgbA((uint32_t*) outPixels, inPixels, width); - outPixels = SkTAddOffset(outPixels, outRowBytes); - inPixels = SkTAddOffset(inPixels, inRowBytes); - } - - return true; -} - // TODO: This will be removed when GrSurfaceContexts are aware of their color types. // (skbug.com/6718) static bool valid_premul_config(GrPixelConfig config) { @@ -450,427 +434,16 @@ static bool valid_pixel_conversion(GrColorType cpuColorType, GrPixelConfig gpuCo return true; } -static bool pm_upm_must_round_trip(GrColorType cpuColorType, const SkColorSpace* cpuColorSpace) { - return !cpuColorSpace && - (GrColorType::kRGBA_8888 == cpuColorType || GrColorType::kBGRA_8888 == cpuColorType); -} - -// TODO: This will be removed when GrSurfaceContexts are aware of their color types. -// (skbug.com/6718) -static bool pm_upm_must_round_trip(GrPixelConfig surfaceConfig, - const SkColorSpace* surfaceColorSpace) { - return !surfaceColorSpace && - (kRGBA_8888_GrPixelConfig == surfaceConfig || kBGRA_8888_GrPixelConfig == surfaceConfig); -} - -static GrSRGBConversion determine_write_pixels_srgb_conversion(GrColorType srcColorType, - const SkColorSpace* srcColorSpace, - GrSRGBEncoded dstSRGBEncoded, - const SkColorSpace* dstColorSpace, - const GrCaps& caps) { - // No support for sRGB-encoded alpha. - if (GrColorTypeIsAlphaOnly(srcColorType)) { - return GrSRGBConversion::kNone; - } - // No conversions without GPU support for sRGB. (Legacy mode) - if (!caps.srgbSupport()) { - return GrSRGBConversion::kNone; - } - // If the GrSurfaceContext has no color space then it is in legacy mode. - if (!dstColorSpace) { - return GrSRGBConversion::kNone; - } - - bool srcColorSpaceIsSRGB = srcColorSpace && srcColorSpace->gammaCloseToSRGB(); - bool dstColorSpaceIsSRGB = dstColorSpace->gammaCloseToSRGB(); - - // For now we are assuming that if color space of the dst does not have sRGB gamma then the - // texture format is not sRGB encoded and vice versa. Note that we already checked for "legacy" - // mode being forced on by caps above. This may change in the future. We will then have to - // perform shader based conversions. - SkASSERT(dstColorSpaceIsSRGB == (GrSRGBEncoded::kYes == dstSRGBEncoded)); - - if (srcColorSpaceIsSRGB == dstColorSpaceIsSRGB) { - return GrSRGBConversion::kNone; - } - return srcColorSpaceIsSRGB ? GrSRGBConversion::kSRGBToLinear : GrSRGBConversion::kLinearToSRGB; -} - -static GrSRGBConversion determine_read_pixels_srgb_conversion(GrSRGBEncoded srcSRGBEncoded, - const SkColorSpace* srcColorSpace, - GrColorType dstColorType, - const SkColorSpace* dstColorSpace, - const GrCaps& caps) { - // This is symmetrical with the write version. - switch (determine_write_pixels_srgb_conversion(dstColorType, dstColorSpace, srcSRGBEncoded, - srcColorSpace, caps)) { - case GrSRGBConversion::kNone: return GrSRGBConversion::kNone; - case GrSRGBConversion::kLinearToSRGB: return GrSRGBConversion::kSRGBToLinear; - case GrSRGBConversion::kSRGBToLinear: return GrSRGBConversion::kLinearToSRGB; - } - return GrSRGBConversion::kNone; -} - bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst, int left, int top, int width, int height, GrColorType srcColorType, SkColorSpace* srcColorSpace, const void* buffer, size_t rowBytes, uint32_t pixelOpsFlags) { - bool useLegacyPath = false; -#ifdef SK_LEGACY_GPU_PIXEL_OPS - useLegacyPath = true; -#endif - // Newly added color types/configs are only supported by the new code path. - if (srcColorType == GrColorType::kRGB_888x || - dst->asSurfaceProxy()->config() == kRGB_888_GrPixelConfig) { - useLegacyPath = false; - } - - if (!useLegacyPath) { - return this->writeSurfacePixels2(dst, left, top, width, height, srcColorType, srcColorSpace, - buffer, rowBytes, pixelOpsFlags); - } - - // TODO: Color space conversion - - ASSERT_SINGLE_OWNER_PRIV - RETURN_FALSE_IF_ABANDONED_PRIV - SkASSERT(dst); - ASSERT_OWNED_PROXY_PRIV(dst->asSurfaceProxy()); - GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "writeSurfacePixels", fContext); - - if (!dst->asSurfaceProxy()->instantiate(this->resourceProvider())) { - return false; - } - - GrSurfaceProxy* dstProxy = dst->asSurfaceProxy(); - GrSurface* dstSurface = dstProxy->priv().peekSurface(); - - // The src is unpremul but the dst is premul -> premul the src before or as part of the write - const bool premul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags); - - if (!valid_pixel_conversion(srcColorType, dstProxy->config(), premul)) { - return false; - } - // There is no way to store alpha values in the dst. - if (GrColorTypeHasAlpha(srcColorType) && GrPixelConfigIsOpaque(dstProxy->config())) { - return false; - } - // The source has no alpha value and the dst is only alpha - if (!GrColorTypeHasAlpha(srcColorType) && GrPixelConfigIsAlphaOnly(dstProxy->config())) { - return false; - } - - // We need to guarantee round-trip conversion if we are reading and writing 8888 non-sRGB data, - // without any color spaces attached, and the caller wants us to premul. - bool useConfigConversionEffect = - premul && pm_upm_must_round_trip(srcColorType, srcColorSpace) && - pm_upm_must_round_trip(dstProxy->config(), dst->colorSpaceInfo().colorSpace()); - - // Are we going to try to premul as part of a draw? For the non-legacy case, we always allow - // this. GrConfigConversionEffect fails on some GPUs, so only allow this if it works perfectly. - bool premulOnGpu = premul && - (!useConfigConversionEffect || fContext->validPMUPMConversionExists()); - - // Trim the params here so that if we wind up making a temporary surface it can be as small as - // necessary and because GrGpu::getWritePixelsInfo requires it. - if (!GrSurfacePriv::AdjustWritePixelParams(dstSurface->width(), dstSurface->height(), - GrColorTypeBytesPerPixel(srcColorType), &left, &top, - &width, &height, &buffer, &rowBytes)) { - return false; - } - - GrGpu::DrawPreference drawPreference = premulOnGpu ? GrGpu::kCallerPrefersDraw_DrawPreference - : GrGpu::kNoDraw_DrawPreference; - GrGpu::WritePixelTempDrawInfo tempDrawInfo; - GrSRGBConversion srgbConversion = determine_write_pixels_srgb_conversion( - srcColorType, srcColorSpace, GrPixelConfigIsSRGBEncoded(dstProxy->config()), - dst->colorSpaceInfo().colorSpace(), *fContext->contextPriv().caps()); - if (!fContext->fGpu->getWritePixelsInfo(dstSurface, dstProxy->origin(), width, height, - srcColorType, srgbConversion, &drawPreference, - &tempDrawInfo)) { - return false; - } - - if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && dstSurface->surfacePriv().hasPendingIO()) { - this->flush(nullptr); // MDB TODO: tighten this - } - - sk_sp tempProxy; - if (GrGpu::kNoDraw_DrawPreference != drawPreference) { - tempProxy = this->proxyProvider()->createProxy(tempDrawInfo.fTempSurfaceDesc, - kTopLeft_GrSurfaceOrigin, - SkBackingFit::kApprox, SkBudgeted::kYes); - if (!tempProxy && GrGpu::kRequireDraw_DrawPreference == drawPreference) { - return false; - } - } - - // temp buffer for doing sw premul conversion, if needed. - SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0); - // We need to do sw premul if we were unable to create a RT for drawing, or if we can't do the - // premul on the GPU - if (premul && (!tempProxy || !premulOnGpu)) { - size_t tmpRowBytes = 4 * width; - tmpPixels.reset(width * height); - if (!sw_convert_to_premul(srcColorType, width, height, rowBytes, buffer, tmpRowBytes, - tmpPixels.get())) { - return false; - } - rowBytes = tmpRowBytes; - buffer = tmpPixels.get(); - } - - if (tempProxy) { - auto fp = GrSimpleTextureEffect::Make(tempProxy, SkMatrix::I()); - if (premulOnGpu) { - fp = fContext->createUPMToPMEffect(std::move(fp), useConfigConversionEffect); - } - fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle); - if (!fp) { - return false; - } - - if (!tempProxy->instantiate(this->resourceProvider())) { - return false; - } - GrTexture* texture = tempProxy->priv().peekTexture(); - - if (tempProxy->priv().hasPendingIO()) { - this->flush(tempProxy.get()); - } - - if (!fContext->fGpu->writePixels(texture, tempProxy->origin(), 0, 0, width, height, - tempDrawInfo.fWriteColorType, buffer, rowBytes)) { - return false; - } - tempProxy = nullptr; - - SkMatrix matrix; - matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top)); - GrRenderTargetContext* renderTargetContext = dst->asRenderTargetContext(); - if (!renderTargetContext) { - return false; - } - GrPaint paint; - paint.addColorFragmentProcessor(std::move(fp)); - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); - SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); - renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix, rect, - nullptr); - - if (kFlushWrites_PixelOp & pixelOpsFlags) { - this->flushSurfaceWrites(renderTargetContext->asRenderTargetProxy()); - } - } else { - return fContext->fGpu->writePixels(dstSurface, dstProxy->origin(), left, top, width, height, - srcColorType, buffer, rowBytes); - } - return true; -} - -bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src, int left, int top, int width, - int height, GrColorType dstColorType, - SkColorSpace* dstColorSpace, void* buffer, size_t rowBytes, - uint32_t flags) { - bool useLegacyPath = false; -#ifdef SK_LEGACY_GPU_PIXEL_OPS - useLegacyPath = true; -#endif - // Newly added color types/configs are only supported by the new code path. - if (dstColorType == GrColorType::kRGB_888x || - src->asSurfaceProxy()->config() == kRGB_888_GrPixelConfig) { - useLegacyPath = false; - } - - if (!useLegacyPath) { - return this->readSurfacePixels2(src, left, top, width, height, dstColorType, dstColorSpace, - buffer, rowBytes, flags); - } - - // TODO: Color space conversion - - ASSERT_SINGLE_OWNER_PRIV - RETURN_FALSE_IF_ABANDONED_PRIV - SkASSERT(src); - ASSERT_OWNED_PROXY_PRIV(src->asSurfaceProxy()); - GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "readSurfacePixels", fContext); - SkASSERT(!(flags & kDontFlush_PixelOpsFlag)); - if (flags & kDontFlush_PixelOpsFlag) { - return false; - } - - // MDB TODO: delay this instantiation until later in the method - if (!src->asSurfaceProxy()->instantiate(this->resourceProvider())) { - return false; - } - - GrSurfaceProxy* srcProxy = src->asSurfaceProxy(); - GrSurface* srcSurface = srcProxy->priv().peekSurface(); - - // The src is premul but the dst is unpremul -> unpremul the src after or as part of the read - bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags); - - if (!valid_pixel_conversion(dstColorType, srcProxy->config(), unpremul)) { - return false; - } - // The source is alpha-only but the dst is not. TODO: Make non-alpha channels in the dst be 0? - if (GrPixelConfigIsAlphaOnly(srcProxy->config()) && !GrColorTypeIsAlphaOnly(dstColorType)) { - return false; - } - // The source has no alpha, the dst is alpha-only. TODO: set all values in dst to 1? - if (GrPixelConfigIsOpaque(srcProxy->config()) && GrColorTypeIsAlphaOnly(dstColorType)) { - return false; - } - // Not clear if we should unpremul in this case. - if (!GrPixelConfigIsOpaque(srcProxy->config()) && !GrColorTypeHasAlpha(dstColorType)) { - return false; - } - - // We need to guarantee round-trip conversion if we are reading and writing 8888 non-sRGB data, - // without any color spaces attached, and the caller wants us to unpremul. - bool useConfigConversionEffect = - unpremul && - pm_upm_must_round_trip(srcProxy->config(), src->colorSpaceInfo().colorSpace()) && - pm_upm_must_round_trip(dstColorType, dstColorSpace); - - // Are we going to try to unpremul as part of a draw? For the non-legacy case, we always allow - // this. GrConfigConversionEffect fails on some GPUs, so only allow this if it works perfectly. - bool unpremulOnGpu = unpremul && - (!useConfigConversionEffect || fContext->validPMUPMConversionExists()); - - // Adjust the params so that if we wind up using an intermediate surface we've already done - // all the trimming and the temporary can be the min size required. - if (!GrSurfacePriv::AdjustReadPixelParams(srcSurface->width(), srcSurface->height(), - GrColorTypeBytesPerPixel(dstColorType), &left, &top, - &width, &height, &buffer, &rowBytes)) { - return false; - } - - GrGpu::DrawPreference drawPreference = unpremulOnGpu ? GrGpu::kCallerPrefersDraw_DrawPreference - : GrGpu::kNoDraw_DrawPreference; - GrGpu::ReadPixelTempDrawInfo tempDrawInfo; - GrSRGBConversion srgbConversion = determine_read_pixels_srgb_conversion( - GrPixelConfigIsSRGBEncoded(srcProxy->config()), src->colorSpaceInfo().colorSpace(), - dstColorType, dstColorSpace, *fContext->contextPriv().caps()); - - if (!fContext->fGpu->getReadPixelsInfo(srcSurface, srcProxy->origin(), width, height, rowBytes, - dstColorType, srgbConversion, &drawPreference, - &tempDrawInfo)) { - return false; - } - - if (srcSurface->surfacePriv().hasPendingWrite()) { - this->flush(nullptr); // MDB TODO: tighten this - } - - sk_sp proxyToRead = src->asSurfaceProxyRef(); - bool didTempDraw = false; - if (GrGpu::kNoDraw_DrawPreference != drawPreference) { - if (SkBackingFit::kExact == tempDrawInfo.fTempSurfaceFit) { - // We only respect this when the entire src is being read. Otherwise we can trigger too - // many odd ball texture sizes and trash the cache. - if (width != srcSurface->width() || height != srcSurface->height()) { - tempDrawInfo.fTempSurfaceFit= SkBackingFit::kApprox; - } - } - // TODO: Need to decide the semantics of this function for color spaces. Do we support - // conversion to a passed-in color space? For now, specifying nullptr means that this - // path will do no conversion, so it will match the behavior of the non-draw path. For - // now we simply infer an sRGB color space if the config is sRGB in order to avoid an - // illegal combination. - sk_sp colorSpace; - if (GrPixelConfigIsSRGB(tempDrawInfo.fTempSurfaceDesc.fConfig)) { - colorSpace = SkColorSpace::MakeSRGB(); - } - sk_sp tempRTC = - fContext->contextPriv().makeDeferredRenderTargetContext( - tempDrawInfo.fTempSurfaceFit, - tempDrawInfo.fTempSurfaceDesc.fWidth, - tempDrawInfo.fTempSurfaceDesc.fHeight, - tempDrawInfo.fTempSurfaceDesc.fConfig, - std::move(colorSpace), - tempDrawInfo.fTempSurfaceDesc.fSampleCnt, - GrMipMapped::kNo, - kTopLeft_GrSurfaceOrigin); - if (tempRTC) { - // Adding discard to appease vulkan validation warning about loading uninitialized data - // on draw - tempRTC->discard(); - SkMatrix textureMatrix = SkMatrix::MakeTrans(SkIntToScalar(left), SkIntToScalar(top)); - sk_sp proxy = src->asTextureProxyRef(); - auto fp = GrSimpleTextureEffect::Make(std::move(proxy), textureMatrix); - if (unpremulOnGpu) { - fp = fContext->createPMToUPMEffect(std::move(fp), useConfigConversionEffect); - // We no longer need to do this on CPU after the read back. - unpremul = false; - } - fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle); - if (!fp) { - return false; - } - - GrPaint paint; - paint.addColorFragmentProcessor(std::move(fp)); - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); - SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); - tempRTC->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect, - nullptr); - proxyToRead = tempRTC->asTextureProxyRef(); - left = 0; - top = 0; - didTempDraw = true; - } - } - - if (!proxyToRead) { - return false; - } - - if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) { - return false; - } - GrColorType colorTypeToRead = dstColorType; - if (didTempDraw) { - this->flushSurfaceWrites(proxyToRead.get()); - colorTypeToRead = tempDrawInfo.fReadColorType; - } - - if (!proxyToRead->instantiate(this->resourceProvider())) { - return false; - } - - GrSurface* surfaceToRead = proxyToRead->priv().peekSurface(); - - if (!fContext->fGpu->readPixels(surfaceToRead, proxyToRead->origin(), left, top, width, height, - colorTypeToRead, buffer, rowBytes)) { - return false; - } - - // Perform umpremul conversion if we weren't able to perform it as a draw. - if (unpremul) { - SkColorType colorType = GrColorTypeToSkColorType(dstColorType); - if (kUnknown_SkColorType == colorType || 4 != SkColorTypeBytesPerPixel(colorType)) { - return false; - } - - for (int y = 0; y < height; y++) { - SkUnpremultiplyRow((uint32_t*) buffer, (const uint32_t*) buffer, width); - buffer = SkTAddOffset(buffer, rowBytes); - } - } - return true; -} - -bool GrContextPriv::writeSurfacePixels2(GrSurfaceContext* dst, int left, int top, int width, - int height, GrColorType srcColorType, - SkColorSpace* srcColorSpace, const void* buffer, - size_t rowBytes, uint32_t pixelOpsFlags) { ASSERT_SINGLE_OWNER_PRIV RETURN_FALSE_IF_ABANDONED_PRIV SkASSERT(dst); SkASSERT(buffer); ASSERT_OWNED_PROXY_PRIV(dst->asSurfaceProxy()); - GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "writeSurfacePixels2", fContext); + GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "writeSurfacePixels", fContext); if (GrColorType::kUnknown == srcColorType) { return false; @@ -934,8 +507,8 @@ bool GrContextPriv::writeSurfacePixels2(GrSurfaceContext* dst, int left, int top // the intermediate surface which gets corrected by a swizzle effect when drawing to the // dst. auto tmpColorType = canvas2DFastPath ? GrColorType::kRGBA_8888 : srcColorType; - if (!this->writeSurfacePixels2(tempCtx.get(), 0, 0, width, height, tmpColorType, - srcColorSpace, buffer, rowBytes, flags)) { + if (!this->writeSurfacePixels(tempCtx.get(), 0, 0, width, height, tmpColorType, + srcColorSpace, buffer, rowBytes, flags)) { return false; } if (canvas2DFastPath) { @@ -1030,16 +603,16 @@ bool GrContextPriv::writeSurfacePixels2(GrSurfaceContext* dst, int left, int top rowBytes); } -bool GrContextPriv::readSurfacePixels2(GrSurfaceContext* src, int left, int top, int width, - int height, GrColorType dstColorType, - SkColorSpace* dstColorSpace, void* buffer, size_t rowBytes, - uint32_t pixelOpsFlags) { +bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src, int left, int top, int width, + int height, GrColorType dstColorType, + SkColorSpace* dstColorSpace, void* buffer, size_t rowBytes, + uint32_t pixelOpsFlags) { ASSERT_SINGLE_OWNER_PRIV RETURN_FALSE_IF_ABANDONED_PRIV SkASSERT(src); SkASSERT(buffer); ASSERT_OWNED_PROXY_PRIV(src->asSurfaceProxy()); - GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "readSurfacePixels2", fContext); + GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "readSurfacePixels", fContext); SkASSERT(!(pixelOpsFlags & kDontFlush_PixelOpsFlag)); if (pixelOpsFlags & kDontFlush_PixelOpsFlag) { @@ -1070,7 +643,7 @@ bool GrContextPriv::readSurfacePixels2(GrSurfaceContext* src, int left, int top, // This is the getImageData equivalent to the canvas2D putImageData fast path. We probably don't // care so much about getImageData performance. However, in order to ensure putImageData/ // getImageData in "legacy" mode are round-trippable we use the GPU to do the complementary - // unpremul step to writeSurfacePixels2's premul step (which is determined empirically in + // unpremul step to writeSurfacePixels's premul step (which is determined empirically in // fContext->vaildaPMUPMConversionExists()). bool canvas2DFastPath = unpremul && @@ -1130,8 +703,8 @@ bool GrContextPriv::readSurfacePixels2(GrSurfaceContext* src, int left, int top, return false; } uint32_t flags = canvas2DFastPath ? 0 : pixelOpsFlags; - return this->readSurfacePixels2(tempCtx.get(), 0, 0, width, height, dstColorType, - dstColorSpace, buffer, rowBytes, flags); + return this->readSurfacePixels(tempCtx.get(), 0, 0, width, height, dstColorType, + dstColorSpace, buffer, rowBytes, flags); } bool convert = unpremul; diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h index 7e6ecb8310..84de0560fa 100644 --- a/src/gpu/GrContextPriv.h +++ b/src/gpu/GrContextPriv.h @@ -130,9 +130,7 @@ public: }; /** - * Reads a rectangle of pixels from a surface. There are currently two versions of this. - * readSurfacePixels() is the older version which will be replaced by the more robust and - * maintainable (but perhaps slower) readSurfacePixels2(). + * Reads a rectangle of pixels from a surface. * * @param src the surface context to read from. * @param left left edge of the rectangle to read (inclusive) @@ -152,14 +150,9 @@ public: bool readSurfacePixels(GrSurfaceContext* src, int left, int top, int width, int height, GrColorType dstColorType, SkColorSpace* dstColorSpace, void* buffer, size_t rowBytes = 0, uint32_t pixelOpsFlags = 0); - bool readSurfacePixels2(GrSurfaceContext* src, int left, int top, int width, int height, - GrColorType dstColorType, SkColorSpace* dstColorSpace, void* buffer, - size_t rowBytes = 0, uint32_t pixelOpsFlags = 0); /** - * Writes a rectangle of pixels to a surface. There are currently two versions of this. - * writeSurfacePixels() is the older version which will be replaced by the more robust and - * maintainable (but perhaps slower) writeSurfacePixels2(). + * Writes a rectangle of pixels to a surface. * * @param dst the surface context to write to. * @param left left edge of the rectangle to write (inclusive) @@ -178,9 +171,6 @@ public: bool writeSurfacePixels(GrSurfaceContext* dst, int left, int top, int width, int height, GrColorType srcColorType, SkColorSpace* srcColorSpace, const void* buffer, size_t rowBytes, uint32_t pixelOpsFlags = 0); - bool writeSurfacePixels2(GrSurfaceContext* dst, int left, int top, int width, int height, - GrColorType srcColorType, SkColorSpace* srcColorSpace, - const void* buffer, size_t rowBytes, uint32_t pixelOpsFlags = 0); GrBackend getBackend() const { return fContext->fBackend; } diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 725a534bc3..8d0cb7f4bb 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -214,90 +214,6 @@ bool GrGpu::copySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, canDiscardOutsideDstRect); } -bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin, int width, - int height, size_t rowBytes, GrColorType dstColorType, - GrSRGBConversion srgbConversion, DrawPreference* drawPreference, - ReadPixelTempDrawInfo* tempDrawInfo) { - SkASSERT(drawPreference); - SkASSERT(tempDrawInfo); - SkASSERT(srcSurface); - SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference); - - // We currently do not support reading into the packed formats 565 or 4444 as they are not - // required to have read back support on all devices and backends. - if (GrColorType::kRGB_565 == dstColorType || GrColorType::kABGR_4444 == dstColorType) { - return false; - } - - GrPixelConfig tempSurfaceConfig = kUnknown_GrPixelConfig; - // GrGpu::readPixels doesn't do any sRGB conversions, so we must draw if there is one. - switch (srgbConversion) { - case GrSRGBConversion::kNone: - // We support reading from RGBA to just A. In that case there is no sRGB version of the - // dst format but we still want to succeed. - if (GrColorTypeIsAlphaOnly(dstColorType)) { - tempSurfaceConfig = GrColorTypeToPixelConfig(dstColorType, GrSRGBEncoded::kNo); - } else { - tempSurfaceConfig = GrColorTypeToPixelConfig( - dstColorType, GrPixelConfigIsSRGBEncoded(srcSurface->config())); - } - break; - case GrSRGBConversion::kLinearToSRGB: - SkASSERT(this->caps()->srgbSupport()); - tempSurfaceConfig = GrColorTypeToPixelConfig(dstColorType, GrSRGBEncoded::kYes); - // Currently we don't expect to make a SRGB encoded surface and then read data from it - // such that we treat it as though it were linear and is then converted to sRGB. - if (GrPixelConfigIsSRGB(srcSurface->config())) { - return false; - } - ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); - break; - case GrSRGBConversion::kSRGBToLinear: - SkASSERT(this->caps()->srgbSupport()); - tempSurfaceConfig = GrColorTypeToPixelConfig(dstColorType, GrSRGBEncoded::kNo); - // We don't currently support reading sRGB encoded data into linear from a surface - // unless it is an sRGB-encoded config. That is likely to change when we need to store - // sRGB encoded data in 101010102 and F16 textures. We'll have to provoke the caller to - // do the conversion in a shader. - if (GrSRGBEncoded::kNo == GrPixelConfigIsSRGBEncoded(srcSurface->config())) { - return false; - } - ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); - break; - } - if (kUnknown_GrPixelConfig == tempSurfaceConfig) { - return false; - } - - // Default values for intermediate draws. The intermediate texture config matches the dst's - // config, is approx sized to the read rect, no swizzling or spoofing of the dst config. - tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag; - tempDrawInfo->fTempSurfaceDesc.fWidth = width; - tempDrawInfo->fTempSurfaceDesc.fHeight = height; - tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 1; - tempDrawInfo->fTempSurfaceDesc.fConfig = tempSurfaceConfig; - tempDrawInfo->fTempSurfaceFit = SkBackingFit::kApprox; - tempDrawInfo->fSwizzle = GrSwizzle::RGBA(); - tempDrawInfo->fReadColorType = dstColorType; - - if (!this->onGetReadPixelsInfo(srcSurface, srcOrigin, width, height, rowBytes, dstColorType, - drawPreference, tempDrawInfo)) { - return false; - } - - // Check to see if we're going to request that the caller draw when drawing is not possible. - if (!srcSurface->asTexture() || - !this->caps()->isConfigRenderable(tempDrawInfo->fTempSurfaceDesc.fConfig)) { - // If we don't have a fallback to a straight read then fail. - if (kRequireDraw_DrawPreference == *drawPreference) { - return false; - } - *drawPreference = kNoDraw_DrawPreference; - } - - return true; -} - bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin, int width, int height, GrColorType srcColorType, GrSRGBConversion srgbConversion, DrawPreference* drawPreference, diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 31870dc833..7c92795c50 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -141,34 +141,6 @@ public: */ void resolveRenderTarget(GrRenderTarget*); - /** Info struct returned by getReadPixelsInfo about performing intermediate draws before - reading pixels for performance or correctness. */ - struct ReadPixelTempDrawInfo { - /** - * If the GrGpu is requesting that the caller do a draw to an intermediate surface then - * this is descriptor for the temp surface. The draw should always be a rect with dst - * 0,0,w,h. - */ - GrSurfaceDesc fTempSurfaceDesc; - /** - * Indicates whether there is a performance advantage to using an exact match texture - * (in terms of width and height) for the intermediate texture instead of approximate. - */ - SkBackingFit fTempSurfaceFit; - /** - * Swizzle to apply during the draw. This is used to compensate for either feature or - * performance limitations in the underlying 3D API. - */ - GrSwizzle fSwizzle; - /** - * The color type that should be used to read from the temp surface after the draw. This - * may be different than the original read color type in order to compensate for swizzling. - * The read data will effectively be in the original color type. The original gamma - * encoding is always used. - */ - GrColorType fReadColorType; - }; - /** Describes why an intermediate draw must/should be performed before readPixels. */ enum DrawPreference { /** @@ -197,15 +169,6 @@ public: kRequireDraw_DrawPreference }; - /** - * Used to negotiate whether and how an intermediate draw should or must be performed before - * a readPixels call. If this returns false then GrGpu could not deduce an intermediate draw - * that would allow a successful readPixels call. The passed width, height, and rowBytes, - * must be non-zero and already reflect clipping to the src bounds. - */ - bool getReadPixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, size_t rowBytes, - GrColorType, GrSRGBConversion, DrawPreference*, ReadPixelTempDrawInfo*); - /** * Info struct returned by getWritePixelsInfo about performing an intermediate draw in order * to write pixels to a GrSurface for either performance or correctness reasons. @@ -554,9 +517,6 @@ private: virtual GrBuffer* onCreateBuffer(size_t size, GrBufferType intendedType, GrAccessPattern, const void* data) = 0; - virtual bool onGetReadPixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, - size_t rowBytes, GrColorType, DrawPreference*, - ReadPixelTempDrawInfo*) = 0; virtual bool onGetWritePixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, GrColorType, DrawPreference*, WritePixelTempDrawInfo*) = 0; diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 3c4b1e8bca..f73a3138af 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -2069,32 +2069,6 @@ void GrGLGpu::clearStencilClip(const GrFixedClip& clip, fHWStencilSettings.invalidate(); } -static bool read_pixels_pays_for_y_flip(GrSurfaceOrigin origin, const GrGLCaps& caps, - int width, int height, GrPixelConfig config, - size_t rowBytes) { - // If the surface is already TopLeft, we don't need to flip. - if (kTopLeft_GrSurfaceOrigin == origin) { - return false; - } - - // If the read is really small or smaller than the min texture size, don't force a draw. - static const int kMinSize = 32; - if (width < kMinSize || height < kMinSize) { - return false; - } - - // if GL can do the flip then we'll never pay for it. - if (caps.packFlipYSupport()) { - return false; - } - - // If we have to do memcpy to handle non-trim rowBytes then we - // get the flip for free. Otherwise it costs. - // Note that we're assuming that 0 rowBytes has already been handled and that the width has been - // clipped. - return caps.packRowLengthSupport() || GrBytesPerPixel(config) * width == rowBytes; -} - bool GrGLGpu::readPixelsSupported(GrRenderTarget* target, GrPixelConfig readConfig) { #ifdef SK_BUILD_FOR_MAC // Chromium may ask us to read back from locked IOSurfaces. Calling the command buffer's @@ -2165,112 +2139,6 @@ bool GrGLGpu::readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig rea } } -bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin, int width, - int height, size_t rowBytes, GrColorType dstColorType, - DrawPreference* drawPreference, - ReadPixelTempDrawInfo* tempDrawInfo) { - // We don't want to introduce a sRGB conversion if we trigger a draw. - auto dstConfigSRGBEncoded = GrPixelConfigIsSRGBEncoded(srcSurface->config()); - if (*drawPreference != kNoDraw_DrawPreference) { - // We assume the base class has only inserted a draw for sRGB reasons. So the - // the temp surface has the config of the dst data. There is no swizzling, nor dst config - // spoofing. - SkASSERT(tempDrawInfo->fReadColorType == dstColorType); - SkASSERT(GrPixelConfigToColorType(tempDrawInfo->fTempSurfaceDesc.fConfig) == dstColorType); - SkASSERT(tempDrawInfo->fSwizzle == GrSwizzle::RGBA()); - // Don't undo a sRGB conversion introduced by our caller via an intermediate draw. - dstConfigSRGBEncoded = GrPixelConfigIsSRGBEncoded(tempDrawInfo->fTempSurfaceDesc.fConfig); - } - if (GrColorTypeIsAlphaOnly(dstColorType)) { - dstConfigSRGBEncoded = GrSRGBEncoded::kNo; - } - GrPixelConfig srcConfig = srcSurface->config(); - - tempDrawInfo->fTempSurfaceFit = this->glCaps().partialFBOReadIsSlow() ? SkBackingFit::kExact - : SkBackingFit::kApprox; - - // TODO: Update this logic to use color type. - auto dstAsConfig = GrColorTypeToPixelConfig(dstColorType, dstConfigSRGBEncoded); - - if (this->glCaps().rgba8888PixelsOpsAreSlow() && kRGBA_8888_GrPixelConfig == dstAsConfig && - this->readPixelsSupported(kBGRA_8888_GrPixelConfig, kBGRA_8888_GrPixelConfig)) { - tempDrawInfo->fTempSurfaceDesc.fConfig = kBGRA_8888_GrPixelConfig; - tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); - tempDrawInfo->fReadColorType = GrColorType::kBGRA_8888; - ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference); - } else if (this->glCaps().rgbaToBgraReadbackConversionsAreSlow() && - GrBytesPerPixel(dstAsConfig) == 4 && - GrPixelConfigSwapRAndB(dstAsConfig) == srcConfig && - this->readPixelsSupported(srcSurface, srcConfig)) { - // Mesa 3D takes a slow path on when reading back BGRA from an RGBA surface and vice-versa. - // Better to do a draw with a R/B swap and then read as the original config. - tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig; - tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); - tempDrawInfo->fReadColorType = GrPixelConfigToColorType(srcConfig); - ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference); - } else if (!this->readPixelsSupported(srcSurface, dstAsConfig)) { - if (kBGRA_8888_GrPixelConfig == dstAsConfig && - this->glCaps().canConfigBeFBOColorAttachment(kRGBA_8888_GrPixelConfig) && - this->readPixelsSupported(kRGBA_8888_GrPixelConfig, kRGBA_8888_GrPixelConfig)) { - // We're trying to read BGRA but it's not supported. If RGBA is renderable and - // we can read it back, then do a swizzling draw to a RGBA and read it back (which - // will effectively be BGRA). - tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig; - tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); - tempDrawInfo->fReadColorType = GrColorType::kRGBA_8888; - ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); - } else if (kSBGRA_8888_GrPixelConfig == dstAsConfig && - this->glCaps().canConfigBeFBOColorAttachment(kSRGBA_8888_GrPixelConfig) && - this->readPixelsSupported(kSRGBA_8888_GrPixelConfig, - kSRGBA_8888_GrPixelConfig)) { - // We're trying to read sBGRA but it's not supported. If sRGBA is renderable and - // we can read it back, then do a swizzling draw to a sRGBA and read it back (which - // will effectively be sBGRA). - tempDrawInfo->fTempSurfaceDesc.fConfig = kSRGBA_8888_GrPixelConfig; - tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); - tempDrawInfo->fReadColorType = GrColorType::kRGBA_8888; - ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); - } else if (kAlpha_8_GrPixelConfig == dstAsConfig) { - // onReadPixels implements a fallback for cases where we want to read kAlpha_8, - // it's unsupported, but 32bit RGBA reads are supported. - if (!this->readPixelsSupported(srcSurface, kRGBA_8888_GrPixelConfig)) { - // If we can't read RGBA from the src try to draw to a kRGBA_8888 (or kSRGBA_8888) - // first and then onReadPixels will read that to a 32bit temporary buffer. - if (this->glCaps().canConfigBeFBOColorAttachment(kRGBA_8888_GrPixelConfig)) { - ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); - tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig; - tempDrawInfo->fReadColorType = GrColorType::kAlpha_8; - } else { - return false; - } - } else { - tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig; - SkASSERT(tempDrawInfo->fReadColorType == GrColorType::kAlpha_8); - } - } else if (kRGBA_half_GrPixelConfig == dstAsConfig && - this->readPixelsSupported(srcSurface, kRGBA_float_GrPixelConfig)) { - // If reading in half float format is not supported, then read in float format. - return true; - } else if (this->glCaps().canConfigBeFBOColorAttachment(dstAsConfig) && - this->readPixelsSupported(dstAsConfig, dstAsConfig)) { - // Do a draw to convert from the src config to the read config. - ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); - tempDrawInfo->fTempSurfaceDesc.fConfig = dstAsConfig; - tempDrawInfo->fReadColorType = dstColorType; - } else { - return false; - } - } - - if ((srcSurface->asRenderTarget() || this->glCaps().canConfigBeFBOColorAttachment(srcConfig)) && - read_pixels_pays_for_y_flip(srcOrigin, this->glCaps(), width, height, dstAsConfig, - rowBytes)) { - ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference); - } - - return true; -} - bool GrGLGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin, int left, int top, int width, int height, GrColorType dstColorType, void* buffer, size_t rowBytes) { SkASSERT(surface); diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 8bb45c2eb5..e827dbc570 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -231,9 +231,6 @@ private: // variations above, depending on whether the surface is a render target or not. bool readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig readConfig); - bool onGetReadPixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, size_t rowBytes, - GrColorType, DrawPreference*, ReadPixelTempDrawInfo*) override; - bool onGetWritePixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, GrColorType, DrawPreference*, WritePixelTempDrawInfo*) override; diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h index 0b3ef079cf..62064b2b6e 100644 --- a/src/gpu/mock/GrMockGpu.h +++ b/src/gpu/mock/GrMockGpu.h @@ -71,11 +71,6 @@ private: GrBuffer* onCreateBuffer(size_t sizeInBytes, GrBufferType, GrAccessPattern, const void*) override; - bool onGetReadPixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, size_t rowBytes, - GrColorType, DrawPreference*, ReadPixelTempDrawInfo*) override { - return true; - } - bool onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin, int width, int height, GrColorType, DrawPreference*, WritePixelTempDrawInfo*) override { return true; diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h index fedce6ee6c..6b2f3c2933 100644 --- a/src/gpu/mtl/GrMtlGpu.h +++ b/src/gpu/mtl/GrMtlGpu.h @@ -31,12 +31,6 @@ public: id device() const { return fDevice; } - bool onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin origin, int readWidth, - int readHeight, size_t rowBytes, GrColorType readConfig, - DrawPreference*, ReadPixelTempDrawInfo*) override { - return false; - } - bool onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin, int width, int height, GrColorType srcColorType, DrawPreference*, WritePixelTempDrawInfo*) override { diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index 772a92fef2..b9d7ea1f89 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -1849,39 +1849,6 @@ bool GrVkGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, return false; } -bool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin, int width, - int height, size_t rowBytes, GrColorType dstColorType, - DrawPreference* drawPreference, - ReadPixelTempDrawInfo* tempDrawInfo) { - // We don't want to introduce a sRGB conversion if we trigger a draw. - auto dstConfigSRGBEncoded = GrPixelConfigIsSRGBEncoded(srcSurface->config()); - if (*drawPreference != kNoDraw_DrawPreference) { - // We assume the base class has only inserted a draw for sRGB reasons. So the - // the temp surface has the config of the dst data. There is no swizzling nor dst config. - // spoofing. - SkASSERT(tempDrawInfo->fReadColorType == dstColorType); - SkASSERT(GrPixelConfigToColorType(tempDrawInfo->fTempSurfaceDesc.fConfig) == dstColorType); - SkASSERT(tempDrawInfo->fSwizzle == GrSwizzle::RGBA()); - // Don't undo a sRGB conversion introduced by our caller via an intermediate draw. - dstConfigSRGBEncoded = GrPixelConfigIsSRGBEncoded(tempDrawInfo->fTempSurfaceDesc.fConfig); - } - if (GrColorTypeIsAlphaOnly(dstColorType)) { - dstConfigSRGBEncoded = GrSRGBEncoded::kNo; - } - - if (GrPixelConfigToColorType(srcSurface->config()) == dstColorType) { - return true; - } - - // Any config change requires a draw - ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); - tempDrawInfo->fTempSurfaceDesc.fConfig = - GrColorTypeToPixelConfig(dstColorType, dstConfigSRGBEncoded); - tempDrawInfo->fReadColorType = dstColorType; - - return kUnknown_GrPixelConfig != tempDrawInfo->fTempSurfaceDesc.fConfig; -} - bool GrVkGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin, int left, int top, int width, int height, GrColorType dstColorType, void* buffer, size_t rowBytes) { if (GrPixelConfigToColorType(surface->config()) != dstColorType) { diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h index a44ea7230f..ae5447eb9e 100644 --- a/src/gpu/vk/GrVkGpu.h +++ b/src/gpu/vk/GrVkGpu.h @@ -165,9 +165,6 @@ private: GrBuffer* onCreateBuffer(size_t size, GrBufferType type, GrAccessPattern, const void* data) override; - bool onGetReadPixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, size_t rowBytes, - GrColorType, DrawPreference*, ReadPixelTempDrawInfo*) override; - bool onGetWritePixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, GrColorType, DrawPreference*, WritePixelTempDrawInfo*) override; -- cgit v1.2.3