From 9c219785a86ed0c112d8b03119d7a4daf6782fd9 Mon Sep 17 00:00:00 2001 From: Brian Salomon Date: Wed, 2 Oct 2019 22:51:08 +0000 Subject: [PATCH] Revert "SkSurface asynchronous read APIs allow client to extend pixel lifetime" This reverts commit ce240cc6fd8ec95bd051c7df2173dad2ae8f6ad6. Reason for revert: crashing in chrome unit test, abandoned context related? Original change's description: > SkSurface asynchronous read APIs allow client to extend pixel lifetime > > Previously the pixel data passed to the client was only valid during > the client's callback. This meant if the client wanted to defer > processing of the data a copy was necessary. > > Now we pass an object to the callback and the pixel lifetime is tied > to the lifetime of that object. > > The object may be holding a GPU transfer buffer mapped. We don't assume > that the object will be released on the direct GrContext thread. So > when the object is destroyed it posts a message to a new type, > GrClientMappedBufferManager, hanging off the direct context. The direct > context will periodically check for messages and unmap and then unref > buffers so that they can be reused. Currently this is done in > GrContext::performDeferredCleanup() and GrDrawingManager::flush(). > > The old API is kept around for backwards compatibility but it is > reimplemented as a bridge on top of the new mechanism. > > Also a utility function to SkImageInfo is added to directly make a new > info with a specified dimensions rather than passing the width and > height separately to makeWH(). > > Bug: chromium:973403 > Bug: skia:8962 > > Change-Id: Id5cf04235376170142a48e90d3ecd13fd021a2a6 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/245457 > Reviewed-by: Brian Osman > Commit-Queue: Brian Salomon TBR=bsalomon@google.com,brianosman@google.com Change-Id: Ic14cf07a7629b167c9f34a651aa87a0326e74207 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: chromium:973403, skia:8962 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/245721 Reviewed-by: Brian Salomon Commit-Queue: Brian Salomon --- RELEASE_NOTES.txt | 4 - bench/AndroidCodecBench.cpp | 3 +- bench/ReadPixBench.cpp | 2 +- dm/DMSrcSink.cpp | 9 +- fuzz/FuzzMain.cpp | 2 +- gm/asyncrescaleandread.cpp | 174 +++++----- gm/downsamplebitmap.cpp | 2 +- gn/gpu.gni | 2 - include/core/SkImageInfo.h | 10 - include/core/SkSurface.h | 135 +++----- include/gpu/GrContext.h | 17 +- samplecode/SampleImageFilterDAG.cpp | 4 +- src/android/SkAnimatedImage.cpp | 4 +- src/codec/SkCodec.cpp | 2 +- src/codec/SkSampledCodec.cpp | 4 +- src/core/SkBitmap.cpp | 4 +- src/core/SkImageInfo.cpp | 4 +- src/core/SkPixmap.cpp | 4 +- src/core/SkSpecialImage.cpp | 2 +- .../imagefilters/SkArithmeticImageFilter.cpp | 4 +- src/gpu/GrClientMappedBufferManager.cpp | 68 ---- src/gpu/GrClientMappedBufferManager.h | 72 ----- src/gpu/GrContext.cpp | 14 +- src/gpu/GrContextPriv.h | 4 - src/gpu/GrDrawingManager.cpp | 2 - src/gpu/GrRenderTargetContext.cpp | 256 ++++++--------- src/gpu/GrRenderTargetContext.h | 11 +- src/image/SkImage_Lazy.cpp | 4 +- src/image/SkImage_Raster.cpp | 2 +- src/image/SkSurface.cpp | 145 ++------- src/image/SkSurface_Base.h | 24 +- src/image/SkSurface_Gpu.cpp | 25 +- src/image/SkSurface_Gpu.h | 5 +- src/image/SkSurface_Raster.cpp | 2 +- tests/AndroidCodecTest.cpp | 2 +- tests/BitmapCopyTest.cpp | 3 +- tests/CodecAnimTest.cpp | 2 +- tests/CodecTest.cpp | 8 +- tests/ReadPixelsTest.cpp | 305 ++++-------------- tools/fm/fm.cpp | 6 +- 40 files changed, 402 insertions(+), 950 deletions(-) delete mode 100644 src/gpu/GrClientMappedBufferManager.cpp delete mode 100644 src/gpu/GrClientMappedBufferManager.h diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 57d00b4a10..52363a2f9a 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -8,10 +8,6 @@ Milestone 79 [Insert new notes here.] - * New versions of SkSurface async-rescale-and read APIs that allow client to extend - the lifetime of the result data. Old versions are deprecated. - https://review.skia.org/245457 - * Add SkColorInfo. It's dimensionless SkImageInfo. https://review.skia.org/245261 diff --git a/bench/AndroidCodecBench.cpp b/bench/AndroidCodecBench.cpp index 894c21bcaa..96f50c6581 100644 --- a/bench/AndroidCodecBench.cpp +++ b/bench/AndroidCodecBench.cpp @@ -32,7 +32,8 @@ void AndroidCodecBench::onDelayedSetup() { std::unique_ptr codec(SkAndroidCodec::MakeFromData(fData)); SkISize scaledSize = codec->getSampledDimensions(fSampleSize); - fInfo = codec->getInfo().makeDimensions(scaledSize).makeColorType(kN32_SkColorType); + fInfo = codec->getInfo().makeWH(scaledSize.width(), scaledSize.height()) + .makeColorType(kN32_SkColorType); if (kUnpremul_SkAlphaType == fInfo.alphaType()) { fInfo = fInfo.makeAlphaType(kPremul_SkAlphaType); } diff --git a/bench/ReadPixBench.cpp b/bench/ReadPixBench.cpp index c940a9edd3..95aa94ba1f 100644 --- a/bench/ReadPixBench.cpp +++ b/bench/ReadPixBench.cpp @@ -74,7 +74,7 @@ protected: const SkImageInfo info = SkImageInfo::MakeN32Premul(2048, 1024); fSrc.allocPixels(info); fSrc.eraseColor(SK_ColorBLACK); - fDst.allocPixels(info.makeDimensions(info.dimensions())); + fDst.allocPixels(info.makeWH(info.height(), info.width())); } const char* onGetName() override { diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index a2d065f889..b0bc346be3 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -413,7 +413,7 @@ Error CodecSrc::draw(SkCanvas* canvas) const { if ((size.width() <= 10 || size.height() <= 10) && 1.0f != fScale) { return Error::Nonfatal("Scaling very small images is uninteresting."); } - decodeInfo = decodeInfo.makeDimensions(size); + decodeInfo = decodeInfo.makeWH(size.width(), size.height()); const int bpp = decodeInfo.bytesPerPixel(); const size_t rowBytes = size.width() * bpp; @@ -794,7 +794,7 @@ Error AndroidCodecSrc::draw(SkCanvas* canvas) const { if ((size.width() <= 10 || size.height() <= 10) && 1 != fSampleSize) { return Error::Nonfatal("Scaling very small images is uninteresting."); } - decodeInfo = decodeInfo.makeDimensions(size); + decodeInfo = decodeInfo.makeWH(size.width(), size.height()); int bpp = decodeInfo.bytesPerPixel(); size_t rowBytes = size.width() * bpp; @@ -976,7 +976,8 @@ Error ColorCodecSrc::draw(SkCanvas* canvas) const { SkImageInfo info = codec->getInfo(); if (fDecodeToDst) { - info = canvas->imageInfo().makeDimensions(info.dimensions()); + info = canvas->imageInfo().makeWH(info.width(), + info.height()); } SkBitmap bitmap; @@ -1820,7 +1821,7 @@ Error ViaUpright::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkSt SkBitmap uprighted; SkISize size = auto_compute_translate(&upright, bitmap->width(), bitmap->height()); - uprighted.allocPixels(bitmap->info().makeDimensions(size)); + uprighted.allocPixels(bitmap->info().makeWH(size.width(), size.height())); SkCanvas canvas(uprighted); canvas.concat(upright); diff --git a/fuzz/FuzzMain.cpp b/fuzz/FuzzMain.cpp index 923524b07d..aecf19df9c 100644 --- a/fuzz/FuzzMain.cpp +++ b/fuzz/FuzzMain.cpp @@ -428,7 +428,7 @@ static void fuzz_img(sk_sp bytes, uint8_t scale, uint8_t mode) { SkImageInfo decodeInfo = codec->getInfo(); SkISize size = codec->getScaledDimensions(fscale); - decodeInfo = decodeInfo.makeDimensions(size); + decodeInfo = decodeInfo.makeWH(size.width(), size.height()); SkBitmap bitmap; SkCodec::Options options; diff --git a/gm/asyncrescaleandread.cpp b/gm/asyncrescaleandread.cpp index 1b86f55089..386cb33817 100644 --- a/gm/asyncrescaleandread.cpp +++ b/gm/asyncrescaleandread.cpp @@ -20,74 +20,98 @@ #include "tools/Resources.h" #include "tools/ToolUtils.h" -namespace { -struct AsyncContext { - bool fCalled = false; - std::unique_ptr fResult; -}; -} // anonymous namespace - -// Making this a lambda in the test functions caused: -// "error: cannot compile this forwarded non-trivially copyable parameter yet" -// on x86/Win/Clang bot, referring to 'result'. -static void async_callback(void* c, std::unique_ptr result) { - auto context = static_cast(c); - context->fResult = std::move(result); - context->fCalled = true; -}; - // Draws the image to a surface, does a asyncRescaleAndReadPixels of the image, and then sticks // the result in a raster image. static sk_sp do_read_and_scale(SkSurface* surface, const SkIRect& srcRect, const SkImageInfo& ii, SkSurface::RescaleGamma rescaleGamma, SkFilterQuality quality) { - auto* context = new AsyncContext(); - surface->asyncRescaleAndReadPixels(ii, srcRect, rescaleGamma, quality, async_callback, context); - while (!context->fCalled) { - // Only GPU should actually be asynchronous. - SkASSERT(surface->getCanvas()->getGrContext()); - surface->getCanvas()->getGrContext()->checkAsyncWorkCompletion(); - } - if (!context->fResult) { - return nullptr; - } - SkPixmap pixmap(ii, context->fResult->data(0), context->fResult->rowBytes(0)); - auto releasePixels = [](const void*, void* c) { delete static_cast(c); }; - return SkImage::MakeFromRaster(pixmap, releasePixels, context); -} - -static sk_sp do_read_and_scale_yuv(SkSurface* surface, SkYUVColorSpace yuvCS, - const SkIRect& srcRect, SkISize size, - SkSurface::RescaleGamma rescaleGamma, - SkFilterQuality quality, SkScopeExit* cleanup) { - SkASSERT(!(size.width() & 0b1) && !(size.height() & 0b1)); - - SkISize uvSize = {size.width()/2, size.height()/2}; - SkImageInfo yII = SkImageInfo::Make(size, kGray_8_SkColorType, kPremul_SkAlphaType); - SkImageInfo uvII = SkImageInfo::Make(uvSize, kGray_8_SkColorType, kPremul_SkAlphaType); - - AsyncContext context; - surface->asyncRescaleAndReadPixelsYUV420(yuvCS, SkColorSpace::MakeSRGB(), srcRect, size, - rescaleGamma, quality, async_callback, &context); + SkBitmap bmp; + bmp.allocPixels(ii); + SkPaint paint; + paint.setBlendMode(SkBlendMode::kSrc); + struct Context { + SkPixmap fPixmap; + bool fCalled = false; + bool fSucceeded = false; + } context; + SkAssertResult(bmp.peekPixels(&context.fPixmap)); + auto callback = [](void* c, const void* data, size_t rowBytes) { + auto context = reinterpret_cast(c); + context->fCalled = true; + if (!data) { + context->fPixmap.reset(); + return; + } + context->fSucceeded = true; + SkRectMemcpy(context->fPixmap.writable_addr(), context->fPixmap.rowBytes(), data, rowBytes, + context->fPixmap.info().minRowBytes(), context->fPixmap.height()); + }; + surface->asyncRescaleAndReadPixels(ii, srcRect, rescaleGamma, quality, callback, &context); while (!context.fCalled) { // Only GPU should actually be asynchronous. SkASSERT(surface->getCanvas()->getGrContext()); surface->getCanvas()->getGrContext()->checkAsyncWorkCompletion(); } - if (!context.fResult) { + return context.fSucceeded ? SkImage::MakeFromBitmap(bmp) : nullptr; +} + +static sk_sp do_read_and_scale_yuv(SkSurface* surface, SkYUVColorSpace yuvCS, + const SkIRect& srcRect, int dstW, int dstH, + SkSurface::RescaleGamma rescaleGamma, + SkFilterQuality quality, SkScopeExit* cleanup) { + SkASSERT(!(dstW & 0b1) && !(dstH & 0b1)); + + struct Context { + Context(int w, int h) { + SkImageInfo yII = SkImageInfo::Make(w, h, kGray_8_SkColorType, kPremul_SkAlphaType); + SkImageInfo uvII = SkImageInfo::Make(w / 2, h / 2, kGray_8_SkColorType, + kPremul_SkAlphaType); + + fYData.alloc(yII); + fUData.alloc(uvII); + fVData.alloc(uvII); + } + + SkAutoPixmapStorage fYData; + SkAutoPixmapStorage fUData; + SkAutoPixmapStorage fVData; + bool fCalled = false; + bool fSucceeded = false; + } context(dstW, dstH); + + auto callback = [](void* c, const void* data[3], size_t rowBytes[3]) { + auto context = reinterpret_cast(c); + context->fCalled = true; + if (!data) { + return; + } + context->fSucceeded = true; + SkRectMemcpy(context->fYData.writable_addr(), context->fYData.rowBytes(), data[0], + rowBytes[0], context->fYData.width(), context->fYData.height()); + SkRectMemcpy(context->fUData.writable_addr(), context->fUData.rowBytes(), data[1], + rowBytes[1], context->fUData.width(), context->fUData.height()); + SkRectMemcpy(context->fVData.writable_addr(), context->fVData.rowBytes(), data[2], + rowBytes[2], context->fVData.width(), context->fVData.height()); + }; + surface->asyncRescaleAndReadPixelsYUV420(yuvCS, SkColorSpace::MakeSRGB(), srcRect, dstW, dstH, + rescaleGamma, quality, callback, &context); + while (!context.fCalled) { + // Only GPU should actually be asynchronous. + SkASSERT(surface->getCanvas()->getGrContext()); + surface->getCanvas()->getGrContext()->checkAsyncWorkCompletion(); + } + if (!context.fSucceeded) { return nullptr; } auto* gr = surface->getCanvas()->getGrContext(); GrBackendTexture backendTextures[3]; - SkPixmap yPM(yII, context.fResult->data(0), context.fResult->rowBytes(0)); - SkPixmap uPM(uvII, context.fResult->data(1), context.fResult->rowBytes(1)); - SkPixmap vPM(uvII, context.fResult->data(2), context.fResult->rowBytes(2)); - - backendTextures[0] = gr->createBackendTexture(yPM, GrRenderable::kNo, GrProtected::kNo); - backendTextures[1] = gr->createBackendTexture(uPM, GrRenderable::kNo, GrProtected::kNo); - backendTextures[2] = gr->createBackendTexture(vPM, GrRenderable::kNo, GrProtected::kNo); - + backendTextures[0] = gr->createBackendTexture(&context.fYData, 1, + GrRenderable::kNo, GrProtected::kNo); + backendTextures[1] = gr->createBackendTexture(&context.fUData, 1, + GrRenderable::kNo, GrProtected::kNo); + backendTextures[2] = gr->createBackendTexture(&context.fVData, 1, + GrRenderable::kNo, GrProtected::kNo); SkYUVAIndex indices[4] = { { 0, SkColorChannel::kR}, { 1, SkColorChannel::kR}, @@ -104,14 +128,14 @@ static sk_sp do_read_and_scale_yuv(SkSurface* surface, SkYUVColorSpace gr->deleteBackendTexture(backendTextures[2]); }}; - return SkImage::MakeFromYUVATextures(gr, yuvCS, backendTextures, indices, size, + return SkImage::MakeFromYUVATextures(gr, yuvCS, backendTextures, indices, {dstW, dstH}, kTopLeft_GrSurfaceOrigin, SkColorSpace::MakeSRGB()); } // Draws a grid of rescales. The columns are none, low, and high filter quality. The rows are // rescale in src gamma and rescale in linear gamma. static skiagm::DrawResult do_rescale_grid(SkCanvas* canvas, SkSurface* surface, - const SkIRect& srcRect, SkISize newSize, bool doYUV420, + const SkIRect& srcRect, int newW, int newH, bool doYUV420, SkString* errorMsg, int pad = 0) { if (doYUV420) { if (!canvas->getGrContext() || !canvas->getGrContext()->priv().asDirectContext()) { @@ -123,7 +147,7 @@ static skiagm::DrawResult do_rescale_grid(SkCanvas* canvas, SkSurface* surface, *errorMsg = "Not supported on recording/vector backends."; return skiagm::DrawResult::kSkip; } - const auto ii = canvas->imageInfo().makeDimensions(newSize); + const auto ii = canvas->imageInfo().makeWH(newW, newH); SkYUVColorSpace yuvColorSpace = kRec601_SkYUVColorSpace; canvas->save(); @@ -133,7 +157,7 @@ static skiagm::DrawResult do_rescale_grid(SkCanvas* canvas, SkSurface* surface, SkScopeExit cleanup; sk_sp result; if (doYUV420) { - result = do_read_and_scale_yuv(surface, yuvColorSpace, srcRect, newSize, gamma, + result = do_read_and_scale_yuv(surface, yuvColorSpace, srcRect, newW, newH, gamma, quality, &cleanup); if (!result) { errorMsg->printf("YUV420 async call failed. Allowed for now."); @@ -149,17 +173,17 @@ static skiagm::DrawResult do_rescale_grid(SkCanvas* canvas, SkSurface* surface, } } canvas->drawImage(result, 0, 0); - canvas->translate(newSize.width() + pad, 0); + canvas->translate(newW + pad, 0); } canvas->restore(); - canvas->translate(0, newSize.height() + pad); + canvas->translate(0, newH + pad); } canvas->restore(); return skiagm::DrawResult::kOk; } static skiagm::DrawResult do_rescale_image_grid(SkCanvas* canvas, const char* imageFile, - const SkIRect& srcRect, SkISize newSize, + const SkIRect& srcRect, int newW, int newH, bool doYUV420, SkString* errorMsg) { auto image = GetResourceAsImage(imageFile); if (!image) { @@ -171,7 +195,7 @@ static skiagm::DrawResult do_rescale_image_grid(SkCanvas* canvas, const char* im return skiagm::DrawResult::kSkip; } // Turn the image into a surface in order to call the read and rescale API - auto surfInfo = image->imageInfo().makeDimensions(image->dimensions()); + auto surfInfo = image->imageInfo().makeWH(image->width(), image->height()); auto surface = canvas->makeSurface(surfInfo); if (!surface && surfInfo.colorType() == kBGRA_8888_SkColorType) { surfInfo = surfInfo.makeColorType(kRGBA_8888_SkColorType); @@ -188,19 +212,19 @@ static skiagm::DrawResult do_rescale_image_grid(SkCanvas* canvas, const char* im SkPaint paint; paint.setBlendMode(SkBlendMode::kSrc); surface->getCanvas()->drawImage(image, 0, 0, &paint); - return do_rescale_grid(canvas, surface.get(), srcRect, newSize, doYUV420, errorMsg); + return do_rescale_grid(canvas, surface.get(), srcRect, newW, newH, doYUV420, errorMsg); } -#define DEF_RESCALE_AND_READ_GM(IMAGE_FILE, TAG, SRC_RECT, W, H) \ - DEF_SIMPLE_GM_CAN_FAIL(async_rescale_and_read_##TAG, canvas, errorMsg, 3 * W, 2 * H) { \ - ToolUtils::draw_checkerboard(canvas, SK_ColorDKGRAY, SK_ColorLTGRAY, 25); \ - return do_rescale_image_grid(canvas, #IMAGE_FILE, SRC_RECT, {W, H}, false, errorMsg); \ +#define DEF_RESCALE_AND_READ_GM(IMAGE_FILE, TAG, SRC_RECT, W, H) \ + DEF_SIMPLE_GM_CAN_FAIL(async_rescale_and_read_##TAG, canvas, errorMsg, 3 * W, 2 * H) { \ + ToolUtils::draw_checkerboard(canvas, SK_ColorDKGRAY, SK_ColorLTGRAY, 25); \ + return do_rescale_image_grid(canvas, #IMAGE_FILE, SRC_RECT, W, H, false, errorMsg); \ } -#define DEF_RESCALE_AND_READ_YUV_GM(IMAGE_FILE, TAG, SRC_RECT, W, H) \ +#define DEF_RESCALE_AND_READ_YUV_GM(IMAGE_FILE, TAG, SRC_RECT, W, H) \ DEF_SIMPLE_GM_CAN_FAIL(async_rescale_and_read_yuv420_##TAG, canvas, errorMsg, 3 * W, 2 * H) { \ - ToolUtils::draw_checkerboard(canvas, SK_ColorDKGRAY, SK_ColorLTGRAY, 25); \ - return do_rescale_image_grid(canvas, #IMAGE_FILE, SRC_RECT, {W, H}, true, errorMsg); \ + ToolUtils::draw_checkerboard(canvas, SK_ColorDKGRAY, SK_ColorLTGRAY, 25); \ + return do_rescale_image_grid(canvas, #IMAGE_FILE, SRC_RECT, W, H, true, errorMsg); \ } DEF_RESCALE_AND_READ_YUV_GM(images/yellow_rose.webp, rose, SkIRect::MakeXYWH(50, 5, 200, 150), @@ -248,14 +272,16 @@ DEF_SIMPLE_GM_CAN_FAIL(async_rescale_and_read_no_bleed, canvas, errorMsg, 60, 60 static constexpr int kPad = 2; canvas->translate(kPad, kPad); skiagm::DrawResult result; - SkISize downSize = {static_cast(kInner/2), static_cast(kInner / 2)}; - result = do_rescale_grid(canvas, surface.get(), srcRect, downSize, false, errorMsg, kPad); + auto downW = static_cast(kInner / 2); + auto downH = static_cast(kInner / 2); + result = do_rescale_grid(canvas, surface.get(), srcRect, downW, downH, false, errorMsg, kPad); if (result != skiagm::DrawResult::kOk) { return result; } - canvas->translate(0, 2 * downSize.height()); - SkISize upSize = {static_cast(kInner * 3.5), static_cast(kInner * 4.6)}; - result = do_rescale_grid(canvas, surface.get(), srcRect, upSize, false, errorMsg, kPad); + canvas->translate(0, 2 * downH); + auto upW = static_cast(kInner * 3.5); + auto upH = static_cast(kInner * 4.6); + result = do_rescale_grid(canvas, surface.get(), srcRect, upW, upH, false, errorMsg, kPad); if (result != skiagm::DrawResult::kOk) { return result; } diff --git a/gm/downsamplebitmap.cpp b/gm/downsamplebitmap.cpp index ef5963f464..76af66fa9c 100644 --- a/gm/downsamplebitmap.cpp +++ b/gm/downsamplebitmap.cpp @@ -79,7 +79,7 @@ struct DownsampleBitmapGM : public skiagm::GM { static SkBitmap convert_bitmap_format(SkBitmap src, SkImageInfo info) { SkBitmap dst; - dst.allocPixels(info.makeDimensions(src.dimensions())); + dst.allocPixels(info.makeWH(src.width(), src.height())); SkPixmap pm; SkAssertResult(dst.peekPixels(&pm)); diff --git a/gn/gpu.gni b/gn/gpu.gni index 01d1ef727d..a08c5a71e4 100644 --- a/gn/gpu.gni +++ b/gn/gpu.gni @@ -60,8 +60,6 @@ skia_gpu_sources = [ "$_src/gpu/GrBufferAllocPool.h", "$_src/gpu/GrCaps.h", "$_src/gpu/GrCaps.cpp", - "$_src/gpu/GrClientMappedBufferManager.cpp", - "$_src/gpu/GrClientMappedBufferManager.h", "$_src/gpu/GrClip.h", "$_src/gpu/GrClipStackClip.h", "$_src/gpu/GrClipStackClip.cpp", diff --git a/include/core/SkImageInfo.h b/include/core/SkImageInfo.h index 5f0506c3eb..46b5fbde06 100644 --- a/include/core/SkImageInfo.h +++ b/include/core/SkImageInfo.h @@ -560,16 +560,6 @@ public: return Make({newWidth, newHeight}, fColorInfo); } - /** Creates SkImageInfo with the same SkColorType, SkColorSpace, and SkAlphaType, - with dimensions set to newDimensions. - - @param newSize pixel column and row count; must be zero or greater - @return created SkImageInfo - */ - SkImageInfo makeDimensions(SkISize newSize) const { - return Make(newSize, fColorInfo); - } - /** Creates SkImageInfo with same SkColorType, SkColorSpace, width, and height, with SkAlphaType set to newAlphaType. diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h index eaf530490d..3bcaeadf98 100644 --- a/include/core/SkSurface.h +++ b/include/core/SkSurface.h @@ -764,132 +764,69 @@ public: */ bool readPixels(const SkBitmap& dst, int srcX, int srcY); - /** The result from asyncRescaleAndReadPixels() or asyncRescaleAndReadPixelsYUV420(). */ - class AsyncReadResult { - public: - AsyncReadResult(const AsyncReadResult&) = delete; - AsyncReadResult(AsyncReadResult&&) = delete; - AsyncReadResult& operator=(const AsyncReadResult&) = delete; - AsyncReadResult& operator=(AsyncReadResult&&) = delete; - - virtual ~AsyncReadResult() = default; - virtual int count() const = 0; - virtual const void* data(int i) const = 0; - virtual size_t rowBytes(int i) const = 0; - - protected: - AsyncReadResult() = default; - }; - - /** Client-provided context that is passed to client-provided ReadPixelsContext. */ - using ReadPixelsContext = void*; - - /** Client-provided callback to asyncRescaleAndReadPixels() or - asyncRescaleAndReadPixelsYUV420() that is called when read result is ready or on failure. - */ - using ReadPixelsCallback = void(ReadPixelsContext, std::unique_ptr); - - /** Controls the gamma that rescaling occurs in for asyncRescaleAndReadPixels() and - asyncRescaleAndReadPixelsYUV420(). - */ - enum RescaleGamma : bool { kSrc, kLinear }; - - /** Makes surface pixel data available to caller, possibly asynchronously. It can also rescale - the surface pixels. + /** Makes pixel data available to caller, possibly asynchronously. Can perform rescaling. Currently asynchronous reads are only supported on the GPU backend and only when the underlying 3D API supports transfer buffers and CPU/GPU synchronization primitives. In all other cases this operates synchronously. - Data is read from the source sub-rectangle, is optionally converted to a linear gamma, is + Data is read from the source rectangle, is optionally converted to a linear gamma, is rescaled to the size indicated by 'info', is then converted to the color space, color type, - and alpha type of 'info'. A 'srcRect' that is not contained by the bounds of the surface - causes failure. + and alpha type of 'info'. - When the pixel data is ready the caller's ReadPixelsCallback is called with a - AsyncReadResult containing pixel data in the requested color type, alpha type, and color - space. The AsyncReadResult will have count() == 1. Upon failure the callback is called - with nullptr for AsyncReadResult. + When the pixel data is ready the caller's ReadPixelsCallback is called with a pointer to + the data in the requested color type, alpha type, and color space. The data pointer is + only valid for the duration of the callback. - The data is valid for the lifetime of AsyncReadResult with the exception that if the - SkSurface is GPU-backed the data is immediately invalidated if the GrContext is abandoned - or destroyed. + Upon failure the the callback is called with nullptr as the data pointer. - @param info info of the requested pixels - @param srcRect subrectangle of surface to read - @param rescaleGamma controls whether rescaling is done in the surface's gamma or whether - the source data is transformed to a linear gamma before rescaling. - @param rescaleQuality controls the quality (and cost) of the rescaling - @param callback function to call with result of the read - @param context passed to callback + If the src rectangle is not contained by the bounds of the surface then failure occurs. + + Failure is indicated by calling callback with a nullptr for 'data'. + + @param info info of the requested pixels + @param srcRect subrectangle of surface to read + @param rescaleGamma controls whether rescaling is done in the surface's gamma or whether + the source data is transformed to a linear gamma before rescaling. + @param rescaleQuality controls the quality (and cost) of the rescaling + @param callback function to call with result of the read + @param context passed to callback */ + using ReadPixelsContext = void*; + using ReadPixelsCallback = void(ReadPixelsContext, const void* data, size_t rowBytes); + enum RescaleGamma : bool { kSrc, kLinear }; void asyncRescaleAndReadPixels(const SkImageInfo& info, const SkIRect& srcRect, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality, ReadPixelsCallback callback, ReadPixelsContext context); - /** Legacy version of asyncRescaleAndReadPixels() that passes data directly to the callback - rather than using AsyncReadResult. The data is only valid during the lifetime of the - callback. - - Deprecated. - */ - using LegacyReadPixelsCallback = void(ReadPixelsContext, const void* data, size_t rowBytes); - void asyncRescaleAndReadPixels(const SkImageInfo& info, const SkIRect& srcRect, - RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality, - LegacyReadPixelsCallback callback, ReadPixelsContext context); - /** Similar to asyncRescaleAndReadPixels but performs an additional conversion to YUV. The RGB->YUV conversion is controlled by 'yuvColorSpace'. The YUV data is returned as three planes ordered y, u, v. The u and v planes are half the width and height of the resized - rectangle. The y, u, and v values are single bytes. Currently this fails if 'dstSize' - width and height are not even. A 'srcRect' that is not contained by the bounds of the - surface causes failure. + rectangle. Currently this fails if dstW or dstH are not even. - When the pixel data is ready the caller's ReadPixelsCallback is called with a - AsyncReadResult containing the planar data. The AsyncReadResult will have count() == 3. - Upon failure the callback is called with nullptr for AsyncReadResult. - - The data is valid for the lifetime of AsyncReadResult with the exception that if the - SkSurface is GPU-backed the data is immediately invalidated if the GrContext is abandoned - or destroyed. + On failure the callback is called with a null data pointer array. Fails if srcRect is not + contained in the surface bounds. @param yuvColorSpace The transformation from RGB to YUV. Applied to the resized image after it is converted to dstColorSpace. @param dstColorSpace The color space to convert the resized image to, after rescaling. @param srcRect The portion of the surface to rescale and convert to YUV planes. - @param dstSize The size to rescale srcRect to - @param rescaleGamma controls whether rescaling is done in the surface's gamma or whether - the source data is transformed to a linear gamma before rescaling. - @param rescaleQuality controls the quality (and cost) of the rescaling - @param callback function to call with the planar read result - @param context passed to callback + @param dstW The width to rescale srcRect to + @param dstH The height to rescale srcRect to + @param rescaleGamma controls whether rescaling is done in the surface's gamma or whether + the source data is transformed to a linear gamma before rescaling. + @param rescaleQuality controls the quality (and cost) of the rescaling + @param callback function to call with the planar read result + @param context passed to callback */ + using ReadPixelsCallbackYUV420 = void(ReadPixelsContext, const void* data[3], + size_t rowBytes[3]); void asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, - sk_sp dstColorSpace, - const SkIRect& srcRect, - const SkISize& dstSize, - RescaleGamma rescaleGamma, + sk_sp dstColorSpace, const SkIRect& srcRect, + int dstW, int dstH, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality, - ReadPixelsCallback callback, - ReadPixelsContext); - - /** Legacy version of asyncRescaleAndReadPixelsYUV420() that passes data directly to the - callback rather than using AsyncReadResult. The data is only valid during the lifetime of - the callback. - - Deprecated. - */ - using LegacyReadPixelsCallbackYUV420 = void(ReadPixelsContext, const void* data[3], - size_t rowBytes[3]); - void asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, - sk_sp dstColorSpace, - const SkIRect& srcRect, - int dstW, int dstH, - RescaleGamma rescaleGamma, - SkFilterQuality rescaleQuality, - LegacyReadPixelsCallbackYUV420 callback, - ReadPixelsContext); + ReadPixelsCallbackYUV420 callback, ReadPixelsContext); /** Copies SkRect of pixels from the src SkPixmap to the SkSurface. diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index ef3fc0ddc7..26159610f0 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -21,7 +21,6 @@ class GrAtlasManager; class GrBackendSemaphore; class GrCaps; -class GrClientMappedBufferManager; class GrContextPriv; class GrContextThreadSafeProxy; class GrFragmentProcessor; @@ -472,13 +471,6 @@ public: GrBackendTexture createBackendTexture(const SkPixmap srcData[], int numLevels, GrRenderable, GrProtected); - // Helper version of above for a single level. - GrBackendTexture createBackendTexture(const SkPixmap& srcData, - GrRenderable renderable, - GrProtected isProtected) { - return this->createBackendTexture(&srcData, 1, renderable, isProtected); - } - void deleteBackendTexture(GrBackendTexture); // This interface allows clients to pre-compile shaders and populate the runtime program cache. @@ -533,11 +525,16 @@ private: GrContextOptions::PersistentCache* fPersistentCache; GrContextOptions::ShaderErrorHandler* fShaderErrorHandler; - std::unique_ptr fMappedBufferManager; - // TODO: have the GrClipStackClip use renderTargetContexts and rm this friending friend class GrContextPriv; + /** + * These functions create premul <-> unpremul effects, using the specialized round-trip effects + * from GrConfigConversionEffect. + */ + std::unique_ptr createPMToUPMEffect(std::unique_ptr); + std::unique_ptr createUPMToPMEffect(std::unique_ptr); + typedef GrRecordingContext INHERITED; }; diff --git a/samplecode/SampleImageFilterDAG.cpp b/samplecode/SampleImageFilterDAG.cpp index 41340b6f8d..40301d45bd 100644 --- a/samplecode/SampleImageFilterDAG.cpp +++ b/samplecode/SampleImageFilterDAG.cpp @@ -465,8 +465,8 @@ static void draw_dag(SkCanvas* canvas, sk_sp filter, // provided CTM during draw_node calls. FilterNode dag = build_dag(ctm, rect, filter.get()); - sk_sp nodeSurface = - canvas->makeSurface(canvas->imageInfo().makeDimensions(surfaceSize)); + sk_sp nodeSurface = canvas->makeSurface( + canvas->imageInfo().makeWH(surfaceSize.width(), surfaceSize.height())); draw_dag(canvas, nodeSurface.get(), dag); canvas->restore(); diff --git a/src/android/SkAnimatedImage.cpp b/src/android/SkAnimatedImage.cpp index 6db6afde4a..e15a862c45 100644 --- a/src/android/SkAnimatedImage.cpp +++ b/src/android/SkAnimatedImage.cpp @@ -23,7 +23,7 @@ sk_sp SkAnimatedImage::Make(std::unique_ptr cod if (!codec) { return nullptr; } - auto info = codec->getInfo().makeDimensions(scaledSize); + auto info = codec->getInfo().makeWH(scaledSize.width(), scaledSize.height()); return Make(std::move(codec), info, cropRect, std::move(postProcess)); } @@ -40,7 +40,7 @@ sk_sp SkAnimatedImage::Make(std::unique_ptr cod || scaledSize.height() >= decodeInfo.height()) { // Only libwebp can decode to arbitrary smaller sizes. auto dims = codec->getInfo().dimensions(); - decodeInfo = decodeInfo.makeDimensions(dims); + decodeInfo = decodeInfo.makeWH(dims.width(), dims.height()); } auto image = sk_sp(new SkAnimatedImage(std::move(codec), scaledSize, diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp index cc5b9bff6e..0fd776fe44 100644 --- a/src/codec/SkCodec.cpp +++ b/src/codec/SkCodec.cpp @@ -246,7 +246,7 @@ bool zero_rect(const SkImageInfo& dstInfo, void* pixels, size_t rowBytes, } } - const SkImageInfo info = dstInfo.makeDimensions(prevRect.size()); + const SkImageInfo info = dstInfo.makeWH(prevRect.width(), prevRect.height()); const size_t bpp = dstInfo.bytesPerPixel(); const size_t offset = prevRect.x() * bpp + prevRect.y() * rowBytes; void* eraseDst = SkTAddOffset(pixels, offset); diff --git a/src/codec/SkSampledCodec.cpp b/src/codec/SkSampledCodec.cpp index c0c8cf02c4..8e1cf070dc 100644 --- a/src/codec/SkSampledCodec.cpp +++ b/src/codec/SkSampledCodec.cpp @@ -101,7 +101,7 @@ SkCodec::Result SkSampledCodec::onGetAndroidPixels(const SkImageInfo& info, void int scaledSubsetWidth = info.width(); int scaledSubsetHeight = info.height(); - const SkImageInfo scaledInfo = info.makeDimensions(scaledSize); + const SkImageInfo scaledInfo = info.makeWH(scaledSize.width(), scaledSize.height()); { // Although startScanlineDecode expects the bottom and top to match the @@ -211,7 +211,7 @@ SkCodec::Result SkSampledCodec::sampledDecode(const SkImageInfo& info, void* pix const int startY = samplingOffsetY + subsetY; const int dstHeight = info.height(); - const SkImageInfo nativeInfo = info.makeDimensions(nativeSize); + const SkImageInfo nativeInfo = info.makeWH(nativeSize.width(), nativeSize.height()); { // Although startScanlineDecode expects the bottom and top to match the diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index f25991de25..83ecc0c799 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -451,7 +451,7 @@ bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { SkASSERT(static_cast(r.fTop) < static_cast(this->height())); SkBitmap dst; - dst.setInfo(this->info().makeDimensions(r.size()), this->rowBytes()); + dst.setInfo(this->info().makeWH(r.width(), r.height()), this->rowBytes()); dst.setIsVolatile(this->isVolatile()); if (fPixelRef) { @@ -492,7 +492,7 @@ bool SkBitmap::writePixels(const SkPixmap& src, int dstX, int dstY) { } void* dstPixels = this->getAddr(rec.fX, rec.fY); - const SkImageInfo dstInfo = this->info().makeDimensions(rec.fInfo.dimensions()); + const SkImageInfo dstInfo = this->info().makeWH(rec.fInfo.width(), rec.fInfo.height()); SkConvertPixels(dstInfo, dstPixels, this->rowBytes(), rec.fInfo, rec.fPixels, rec.fRowBytes); this->notifyPixelsChanged(); return true; diff --git a/src/core/SkImageInfo.cpp b/src/core/SkImageInfo.cpp index e6e12bccd9..f033bb16ef 100644 --- a/src/core/SkImageInfo.cpp +++ b/src/core/SkImageInfo.cpp @@ -149,7 +149,7 @@ bool SkReadPixelsRec::trim(int srcWidth, int srcHeight) { // we negate and add them so UBSAN (pointer-overflow) doesn't get confused. fPixels = ((char*)fPixels + -y*fRowBytes + -x*fInfo.bytesPerPixel()); // the intersect may have shrunk info's logical size - fInfo = fInfo.makeDimensions(srcR.size()); + fInfo = fInfo.makeWH(srcR.width(), srcR.height()); fX = srcR.x(); fY = srcR.y(); @@ -186,7 +186,7 @@ bool SkWritePixelsRec::trim(int dstWidth, int dstHeight) { // we negate and add them so UBSAN (pointer-overflow) doesn't get confused. fPixels = ((const char*)fPixels + -y*fRowBytes + -x*fInfo.bytesPerPixel()); // the intersect may have shrunk info's logical size - fInfo = fInfo.makeDimensions(dstR.size()); + fInfo = fInfo.makeWH(dstR.width(), dstR.height()); fX = dstR.x(); fY = dstR.y(); diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp index c8a09ff7c7..3da7c1f399 100644 --- a/src/core/SkPixmap.cpp +++ b/src/core/SkPixmap.cpp @@ -76,7 +76,7 @@ bool SkPixmap::extractSubset(SkPixmap* result, const SkIRect& subset) const { const size_t bpp = fInfo.bytesPerPixel(); pixels = (const uint8_t*)fPixels + r.fTop * fRowBytes + r.fLeft * bpp; } - result->reset(fInfo.makeDimensions(r.size()), pixels, fRowBytes); + result->reset(fInfo.makeWH(r.width(), r.height()), pixels, fRowBytes); return true; } @@ -163,7 +163,7 @@ bool SkPixmap::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t ds } const void* srcPixels = this->addr(rec.fX, rec.fY); - const SkImageInfo srcInfo = fInfo.makeDimensions(rec.fInfo.dimensions()); + const SkImageInfo srcInfo = fInfo.makeWH(rec.fInfo.width(), rec.fInfo.height()); SkConvertPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, srcInfo, srcPixels, this->rowBytes()); return true; } diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp index bdd5874fb1..109741abc9 100644 --- a/src/core/SkSpecialImage.cpp +++ b/src/core/SkSpecialImage.cpp @@ -346,7 +346,7 @@ sk_sp SkSpecialImage::CopyFromRaster(const SkIRect& subset, } SkBitmap tmp; - SkImageInfo info = bm.info().makeDimensions(subset.size()); + SkImageInfo info = bm.info().makeWH(subset.width(), subset.height()); // As in MakeFromRaster, must force src to N32 for ImageFilters if (!valid_for_imagefilters(bm.info())) { info = info.makeColorType(kN32_SkColorType); diff --git a/src/effects/imagefilters/SkArithmeticImageFilter.cpp b/src/effects/imagefilters/SkArithmeticImageFilter.cpp index 1da9be1cdc..5ec1909248 100644 --- a/src/effects/imagefilters/SkArithmeticImageFilter.cpp +++ b/src/effects/imagefilters/SkArithmeticImageFilter.cpp @@ -193,10 +193,10 @@ static bool intersect(SkPixmap* dst, SkPixmap* src, int srcDx, int srcDy) { if (!sect.intersect(dstR, srcR)) { return false; } - *dst = SkPixmap(dst->info().makeDimensions(sect.size()), + *dst = SkPixmap(dst->info().makeWH(sect.width(), sect.height()), dst->addr(sect.fLeft, sect.fTop), dst->rowBytes()); - *src = SkPixmap(src->info().makeDimensions(sect.size()), + *src = SkPixmap(src->info().makeWH(sect.width(), sect.height()), src->addr(SkTMax(0, -srcDx), SkTMax(0, -srcDy)), src->rowBytes()); return true; diff --git a/src/gpu/GrClientMappedBufferManager.cpp b/src/gpu/GrClientMappedBufferManager.cpp deleted file mode 100644 index 1d4d922b2a..0000000000 --- a/src/gpu/GrClientMappedBufferManager.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "src/gpu/GrClientMappedBufferManager.h" - -#include - -GrClientMappedBufferManager::~GrClientMappedBufferManager() { - this->process(); - if (!fAbandoned) { - // If we're going down before we got the messages we go ahead and unmap all the buffers. - // It's up to the client to ensure that they aren't being accessed on another thread while - // this is happening (or afterwards on any thread). - for (auto& b : fClientHeldBuffers) { - b->unmap(); - } - } -} - -void GrClientMappedBufferManager::insert(sk_sp b) { - SkDEBUGCODE(auto end = fClientHeldBuffers.end()); - SkASSERT(std::find(fClientHeldBuffers.begin(), end, b) == end); - fClientHeldBuffers.emplace_front(std::move(b)); -} - -void GrClientMappedBufferManager::process() { - SkSTArray<4, BufferFinishedMessage> messages; - fFinishedBufferInbox.poll(&messages); - if (!fAbandoned) { - for (auto& m : messages) { - this->remove(m.fBuffer); - m.fBuffer->unmap(); - } - } -} - -void GrClientMappedBufferManager::abandon() { - fAbandoned = true; - fClientHeldBuffers.clear(); -} - -void GrClientMappedBufferManager::remove(const sk_sp& b) { - // There is no convenient remove only the first element that equals a value functionality in - // std::forward_list. - auto prev = fClientHeldBuffers.before_begin(); - auto end = fClientHeldBuffers.end(); - SkASSERT(std::find(fClientHeldBuffers.begin(), end, b) != end); - for (auto cur = fClientHeldBuffers.begin(); cur != end; prev = cur++) { - if (*cur == b) { - fClientHeldBuffers.erase_after(prev); - break; - } - } - SkASSERT(std::find(fClientHeldBuffers.begin(), end, b) == end); -} - -////////////////////////////////////////////////////////////////////////////// - -DECLARE_SKMESSAGEBUS_MESSAGE(GrClientMappedBufferManager::BufferFinishedMessage) - -bool SkShouldPostMessageToBus(const GrClientMappedBufferManager::BufferFinishedMessage& m, - uint32_t msgBusUniqueID) { - return m.fInboxID == msgBusUniqueID; -} diff --git a/src/gpu/GrClientMappedBufferManager.h b/src/gpu/GrClientMappedBufferManager.h deleted file mode 100644 index fa3243b806..0000000000 --- a/src/gpu/GrClientMappedBufferManager.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrClientMappedBufferManager_DEFINED -#define GrClientMappedBufferManager_DEFINED - -#include "include/private/SkTArray.h" -#include "src/core/SkMessageBus.h" -#include "src/gpu/GrGpuBuffer.h" -#include - -/** - * We sometimes hand clients objects that contain mapped GrGpuBuffers. The client may consume - * the mapped buffer on another thread. This object manages receiving messages that buffers are - * ready to be unmapped (on the direct GrContext's thread). It also handles cleaning up mapped - * buffers if the GrContext is destroyed before the client has finished with the buffer. - * - * Buffers are first registered using insert() before being passed the client. process() should be - * called periodically on the direct GrContext thread to poll for messages and process them. - */ -class GrClientMappedBufferManager final { -public: - /** - * The message type that internal users of this should post to unmap the buffer. - * Set fInboxID to inboxID(). fBuffer must have been previously passed to insert(). - */ - struct BufferFinishedMessage { - sk_sp fBuffer; - uint32_t fInboxID; - }; - using BufferFinishedMessageBus = SkMessageBus; - - GrClientMappedBufferManager() = default; - GrClientMappedBufferManager(const GrClientMappedBufferManager&) = delete; - GrClientMappedBufferManager(GrClientMappedBufferManager&&) = delete; - - ~GrClientMappedBufferManager(); - - GrClientMappedBufferManager& operator=(const GrClientMappedBufferManager&) = delete; - GrClientMappedBufferManager& operator=(GrClientMappedBufferManager&&) = delete; - - /** Initialize BufferFinishedMessage::fInboxID to this value. */ - uint32_t inboxID() const { return fFinishedBufferInbox.uniqueID(); } - - /** - * Let the manager know to expect a message with buffer 'b'. It's illegal for a buffer to be - * inserted again before it is unmapped by process(). - */ - void insert(sk_sp b); - - /** Poll for messages and unmap any incoming buffers. */ - void process(); - - /** Notifies the manager that the context has been abandoned. No more unmaps() will occur.*/ - void abandon(); - -private: - BufferFinishedMessageBus::Inbox fFinishedBufferInbox; - std::forward_list> fClientHeldBuffers; - bool fAbandoned = false; - - void remove(const sk_sp& b); -}; - -bool SkShouldPostMessageToBus(const GrClientMappedBufferManager::BufferFinishedMessage&, - uint32_t msgBusUniqueID); - -#endif diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 4570b13862..a41922de5f 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -5,15 +5,13 @@ * found in the LICENSE file. */ -#include "include/gpu/GrContext.h" - #include "include/core/SkTraceMemoryDump.h" #include "include/gpu/GrBackendSemaphore.h" +#include "include/gpu/GrContext.h" #include "include/private/SkDeferredDisplayList.h" #include "include/private/SkImageInfoPriv.h" #include "src/core/SkMakeUnique.h" #include "src/core/SkTaskGroup.h" -#include "src/gpu/GrClientMappedBufferManager.h" #include "src/gpu/GrDrawingManager.h" #include "src/gpu/GrGpu.h" #include "src/gpu/GrMemoryPool.h" @@ -33,6 +31,7 @@ #include "src/gpu/text/GrTextContext.h" #include "src/image/SkSurface_Gpu.h" #include +#include #define ASSERT_OWNED_PROXY(P) \ SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == this) @@ -98,8 +97,6 @@ bool GrContext::init(sk_sp caps, sk_sp FPFac fShaderErrorHandler = GrShaderUtils::DefaultShaderErrorHandler(); } - fMappedBufferManager = skstd::make_unique(); - return true; } @@ -116,8 +113,6 @@ void GrContext::abandonContext() { INHERITED::abandonContext(); - fMappedBufferManager->abandon(); - fResourceProvider->abandon(); // Need to cleanup the drawing manager first so all the render targets @@ -129,8 +124,6 @@ void GrContext::abandonContext() { fResourceCache->abandonAll(); fGpu->disconnect(GrGpu::DisconnectType::kAbandon); - - fMappedBufferManager.reset(); } void GrContext::releaseResourcesAndAbandonContext() { @@ -140,8 +133,6 @@ void GrContext::releaseResourcesAndAbandonContext() { INHERITED::abandonContext(); - fMappedBufferManager.reset(); - fResourceProvider->abandon(); // Need to cleanup the drawing manager first so all the render targets @@ -193,7 +184,6 @@ void GrContext::performDeferredCleanup(std::chrono::milliseconds msNotUsed) { ASSERT_SINGLE_OWNER - fMappedBufferManager->process(); auto purgeTime = GrStdSteadyClock::now() - msNotUsed; fResourceCache->purgeAsNeeded(); diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h index 64522b065e..399ac575a8 100644 --- a/src/gpu/GrContextPriv.h +++ b/src/gpu/GrContextPriv.h @@ -228,10 +228,6 @@ public: return fContext->fShaderErrorHandler; } - GrClientMappedBufferManager* clientMappedBufferManager() { - return fContext->fMappedBufferManager.get(); - } - #if GR_TEST_UTILS /** Reset GPU stats */ void resetGpuStats() const ; diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp index 65d8059ce4..3507f1b096 100644 --- a/src/gpu/GrDrawingManager.cpp +++ b/src/gpu/GrDrawingManager.cpp @@ -13,7 +13,6 @@ #include "include/private/SkDeferredDisplayList.h" #include "src/core/SkTTopoSort.h" #include "src/gpu/GrAuditTrail.h" -#include "src/gpu/GrClientMappedBufferManager.h" #include "src/gpu/GrContextPriv.h" #include "src/gpu/GrCopyRenderTask.h" #include "src/gpu/GrGpu.h" @@ -249,7 +248,6 @@ GrSemaphoresSubmitted GrDrawingManager::flush(GrSurfaceProxy* proxies[], int num } return GrSemaphoresSubmitted::kNo; // Can't flush while DDL recording } - direct->priv().clientMappedBufferManager()->process(); GrGpu* gpu = direct->priv().getGpu(); if (!gpu) { diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 9f20a15e71..dcd108af49 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -17,7 +17,6 @@ #include "src/core/SkDrawShadowInfo.h" #include "src/core/SkGlyphRunPainter.h" #include "src/core/SkLatticeIter.h" -#include "src/core/SkMakeUnique.h" #include "src/core/SkMatrixPriv.h" #include "src/core/SkRRectPriv.h" #include "src/core/SkSurfacePriv.h" @@ -25,7 +24,6 @@ #include "src/gpu/GrAuditTrail.h" #include "src/gpu/GrBlurUtils.h" #include "src/gpu/GrCaps.h" -#include "src/gpu/GrClientMappedBufferManager.h" #include "src/gpu/GrColor.h" #include "src/gpu/GrContextPriv.h" #include "src/gpu/GrDataUtils.h" @@ -1511,18 +1509,18 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels( SkFilterQuality rescaleQuality, ReadPixelsCallback callback, ReadPixelsContext context) { auto direct = fContext->priv().asDirectContext(); if (!direct) { - callback(context, nullptr); + callback(context, nullptr, 0); return; } if (fRenderTargetProxy->wrapsVkSecondaryCB()) { - callback(context, nullptr); + callback(context, nullptr, 0); return; } auto dstCT = SkColorTypeToGrColorType(info.colorType()); // TODO: Support reading to gray. if (dstCT == GrColorType::kUnknown || GrColorTypeComponentFlags(dstCT) & kGray_SkColorTypeComponentFlag) { - callback(context, nullptr); + callback(context, nullptr, 0); return; } bool needsRescale = srcRect.width() != info.width() || srcRect.height() != info.height(); @@ -1537,7 +1535,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels( backendFormatOfFinalContext, dstCT); // Fail if we can't read from the source surface's color type. if (readInfo.fColorType == GrColorType::kUnknown) { - callback(context, nullptr); + callback(context, nullptr, 0); return; } // Fail if read color type does not have all of dstCT's color channels and those missing color @@ -1546,7 +1544,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels( uint32_t legalReadComponents = GrColorTypeComponentFlags(readInfo.fColorType); uint32_t srcComponents = GrColorTypeComponentFlags(this->colorInfo().colorType()); if ((~legalReadComponents & dstComponents) & srcComponents) { - callback(context, nullptr); + callback(context, nullptr, 0); return; } @@ -1556,7 +1554,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels( if (needsRescale) { tempRTC = this->rescale(info, srcRect, rescaleGamma, rescaleQuality); if (!tempRTC) { - callback(context, nullptr); + callback(context, nullptr, 0); return; } SkASSERT(SkColorSpace::Equals(tempRTC->colorInfo().colorSpace(), info.colorSpace())); @@ -1572,7 +1570,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels( // We flip or color convert by drawing and we don't currently support drawing to // kPremul. if (info.alphaType() == kUnpremul_SkAlphaType) { - callback(context, nullptr); + callback(context, nullptr, 0); return; } sk_sp texProxy = sk_ref_sp(fRenderTargetProxy->asTextureProxy()); @@ -1583,7 +1581,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels( GrMipMapped::kNo, srcRect, SkBackingFit::kApprox, SkBudgeted::kNo); if (!texProxy) { - callback(context, nullptr); + callback(context, nullptr, 0); return; } srcRectToDraw = SkRect::MakeWH(srcRect.width(), srcRect.height()); @@ -1593,7 +1591,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels( this->colorInfo().colorType(), info.refColorSpace(), 1, GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin); if (!tempRTC) { - callback(context, nullptr); + callback(context, nullptr, 0); return; } tempRTC->drawTexture(GrNoClip(), std::move(texProxy), GrSamplerState::Filter::kNearest, @@ -1609,126 +1607,55 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels( info.colorType(), callback, context); } -class GrRenderTargetContext::AsyncReadResult : public SkSurface::AsyncReadResult { -public: - AsyncReadResult(uint32_t inboxID) : fInboxID(inboxID) {} - ~AsyncReadResult() override { - for (int i = 0; i < fPlanes.count(); ++i) { - if (!fPlanes[i].fMappedBuffer) { - delete[] static_cast(fPlanes[i].fData); - } else { - GrClientMappedBufferManager::BufferFinishedMessageBus::Post( - {std::move(fPlanes[i].fMappedBuffer), fInboxID}); - } - } - } - - int count() const override { return fPlanes.count(); } - const void* data(int i) const override { return fPlanes[i].fData; } - size_t rowBytes(int i) const override { return fPlanes[i].fRowBytes; } - - bool addTransferResult(const PixelTransferResult& result, - SkISize size, - size_t rowBytes, - GrClientMappedBufferManager* manager) { - SkASSERT(!result.fTransferBuffer->isMapped()); - const void* mappedData = result.fTransferBuffer->map(); - if (!mappedData) { - return false; - } - if (result.fPixelConverter) { - std::unique_ptr convertedData(new char[rowBytes * size.height()]); - result.fPixelConverter(convertedData.get(), mappedData); - this->addCpuPlane(std::move(convertedData), rowBytes); - result.fTransferBuffer->unmap(); - } else { - manager->insert(result.fTransferBuffer); - this->addMappedPlane(mappedData, rowBytes, std::move(result.fTransferBuffer)); - } - return true; - } - - void addCpuPlane(std::unique_ptr data, size_t rowBytes) { - SkASSERT(data); - SkASSERT(rowBytes > 0); - fPlanes.emplace_back(data.release(), rowBytes, nullptr); - } - -private: - void addMappedPlane(const void* data, size_t rowBytes, sk_sp mappedBuffer) { - SkASSERT(data); - SkASSERT(rowBytes > 0); - SkASSERT(mappedBuffer); - SkASSERT(mappedBuffer->isMapped()); - fPlanes.emplace_back(data, rowBytes, std::move(mappedBuffer)); - } - - struct Plane { - Plane(const void* data, size_t rowBytes, sk_sp buffer) - : fData(data), fRowBytes(rowBytes), fMappedBuffer(std::move(buffer)) {} - const void* fData; - size_t fRowBytes; - // If this is null then fData is heap alloc and must be delete[]ed as const char[]. - sk_sp fMappedBuffer; - }; - SkSTArray<3, Plane> fPlanes; - uint32_t fInboxID; -}; - void GrRenderTargetContext::asyncReadPixels(const SkIRect& rect, SkColorType colorType, ReadPixelsCallback callback, ReadPixelsContext context) { SkASSERT(rect.fLeft >= 0 && rect.fRight <= this->width()); SkASSERT(rect.fTop >= 0 && rect.fBottom <= this->height()); - auto directContext = fContext->priv().asDirectContext(); - SkASSERT(directContext); - auto mappedBufferManager = directContext->priv().clientMappedBufferManager(); - auto transferResult = this->transferPixels(SkColorTypeToGrColorType(colorType), rect); if (!transferResult.fTransferBuffer) { + SkAutoPixmapStorage pm; auto ii = SkImageInfo::Make(rect.size(), colorType, this->colorInfo().alphaType(), this->colorInfo().refColorSpace()); - auto result = skstd::make_unique(0); - std::unique_ptr data(new char[ii.computeMinByteSize()]); - SkPixmap pm(ii, data.get(), ii.minRowBytes()); - result->addCpuPlane(std::move(data), pm.rowBytes()); - + pm.alloc(ii); if (!this->readPixels(ii, pm.writable_addr(), pm.rowBytes(), {rect.fLeft, rect.fTop})) { - callback(context, nullptr); + callback(context, nullptr, 0); } - callback(context, std::move(result)); + callback(context, pm.addr(), pm.rowBytes()); return; } struct FinishContext { ReadPixelsCallback* fClientCallback; ReadPixelsContext fClientContext; - SkISize fSize; + int fW, fH; SkColorType fColorType; - GrClientMappedBufferManager* fMappedBufferManager; PixelTransferResult fTransferResult; }; // Assumption is that the caller would like to flush. We could take a parameter or require an // explicit flush from the caller. We'd have to have a way to defer attaching the finish // callback to GrGpu until after the next flush that flushes our op list, though. - auto* finishContext = new FinishContext{callback, - context, - rect.size(), - colorType, - mappedBufferManager, - std::move(transferResult)}; + auto* finishContext = new FinishContext{callback, context, rect.width(), + rect.height(), colorType, std::move(transferResult)}; auto finishCallback = [](GrGpuFinishedContext c) { const auto* context = reinterpret_cast(c); - auto result = skstd::make_unique(context->fMappedBufferManager->inboxID()); - size_t rowBytes = context->fSize.width() * SkColorTypeBytesPerPixel(context->fColorType); - if (!result->addTransferResult(context->fTransferResult, context->fSize, rowBytes, - context->fMappedBufferManager)) { - result.reset(); + const void* data = context->fTransferResult.fTransferBuffer->map(); + if (!data) { + (*context->fClientCallback)(context->fClientContext, nullptr, 0); + delete context; + return; } - (*context->fClientCallback)(context->fClientContext, std::move(result)); + std::unique_ptr tmp; + size_t rowBytes = context->fW * SkColorTypeBytesPerPixel(context->fColorType); + if (context->fTransferResult.fPixelConverter) { + tmp.reset(new char[rowBytes * context->fH]); + context->fTransferResult.fPixelConverter(tmp.get(), data); + data = tmp.get(); + } + (*context->fClientCallback)(context->fClientContext, data, rowBytes); delete context; }; GrFlushInfo flushInfo; @@ -1737,40 +1664,37 @@ void GrRenderTargetContext::asyncReadPixels(const SkIRect& rect, SkColorType col this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo); } -void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, - sk_sp dstColorSpace, - const SkIRect& srcRect, - const SkISize& dstSize, - RescaleGamma rescaleGamma, - SkFilterQuality rescaleQuality, - ReadPixelsCallback callback, - ReadPixelsContext context) { +void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420( + SkYUVColorSpace yuvColorSpace, sk_sp dstColorSpace, const SkIRect& srcRect, + int dstW, int dstH, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality, + ReadPixelsCallbackYUV420 callback, ReadPixelsContext context) { SkASSERT(srcRect.fLeft >= 0 && srcRect.fRight <= this->width()); SkASSERT(srcRect.fTop >= 0 && srcRect.fBottom <= this->height()); - SkASSERT(!dstSize.isZero()); - SkASSERT((dstSize.width() % 2 == 0) && (dstSize.height() % 2 == 0)); - + SkASSERT((dstW % 2 == 0) && (dstH % 2 == 0)); auto direct = fContext->priv().asDirectContext(); if (!direct) { - callback(context, nullptr); + callback(context, nullptr, nullptr); return; } if (fRenderTargetProxy->wrapsVkSecondaryCB()) { - callback(context, nullptr); + callback(context, nullptr, nullptr); + return; + } + if (dstW & 0x1) { return; } int x = srcRect.fLeft; int y = srcRect.fTop; std::unique_ptr tempRTC; - bool needsRescale = srcRect.size() != dstSize; + 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(dstSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType, + auto info = SkImageInfo::Make(dstW, dstH, kRGBA_8888_SkColorType, kPremul_SkAlphaType, dstColorSpace); // TODO: Incorporate the YUV conversion into last pass of rescaling. tempRTC = this->rescale(info, srcRect, rescaleGamma, rescaleQuality); if (!tempRTC) { - callback(context, nullptr); + callback(context, nullptr, nullptr); return; } SkASSERT(SkColorSpace::Equals(tempRTC->colorInfo().colorSpace(), info.colorSpace())); @@ -1785,16 +1709,15 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC sk_sp texProxy = this->asTextureProxyRef(); // TODO: Do something if the input is not a texture already. if (!texProxy) { - callback(context, nullptr); + callback(context, nullptr, nullptr); return; } SkRect srcRectToDraw = SkRect::Make(srcRect); tempRTC = direct->priv().makeDeferredRenderTargetContext( - SkBackingFit::kApprox, dstSize.width(), dstSize.height(), - this->colorInfo().colorType(), dstColorSpace, 1, GrMipMapped::kNo, - kTopLeft_GrSurfaceOrigin); + SkBackingFit::kApprox, dstW, dstH, this->colorInfo().colorType(), dstColorSpace, + 1, GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin); if (!tempRTC) { - callback(context, nullptr); + callback(context, nullptr, nullptr); return; } tempRTC->drawTexture(GrNoClip(), std::move(texProxy), GrSamplerState::Filter::kNearest, @@ -1808,22 +1731,20 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC auto srcProxy = tempRTC ? tempRTC->asTextureProxyRef() : this->asTextureProxyRef(); // TODO: Do something if the input is not a texture already. if (!srcProxy) { - callback(context, nullptr); + callback(context, nullptr, nullptr); return; } auto yRTC = direct->priv().makeDeferredRenderTargetContextWithFallback( - SkBackingFit::kApprox, dstSize.width(), dstSize.height(), GrColorType::kAlpha_8, - dstColorSpace, 1, GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin); - int halfW = dstSize.width()/2; - int halfH = dstSize.height()/2; + SkBackingFit::kApprox, dstW, dstH, GrColorType::kAlpha_8, dstColorSpace, 1, + GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin); auto uRTC = direct->priv().makeDeferredRenderTargetContextWithFallback( - SkBackingFit::kApprox, halfW, halfH, GrColorType::kAlpha_8, dstColorSpace, 1, + SkBackingFit::kApprox, dstW / 2, dstH / 2, GrColorType::kAlpha_8, dstColorSpace, 1, GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin); auto vRTC = direct->priv().makeDeferredRenderTargetContextWithFallback( - SkBackingFit::kApprox, halfW, halfH, GrColorType::kAlpha_8, dstColorSpace, 1, + SkBackingFit::kApprox, dstW / 2, dstH / 2, GrColorType::kAlpha_8, dstColorSpace, 1, GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin); if (!yRTC || !uRTC || !vRTC) { - callback(context, nullptr); + callback(context, nullptr, nullptr); return; } @@ -1866,8 +1787,8 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC auto texMatrix = SkMatrix::MakeTrans(x, y); - SkRect dstRectY = SkRect::Make(dstSize); - SkRect dstRectUV = SkRect::MakeWH(halfW, halfH); + SkRect dstRectY = SkRect::MakeWH(dstW, dstH); + SkRect dstRectUV = SkRect::MakeWH(dstW / 2, dstH / 2); // This matrix generates (r,g,b,a) = (0, 0, 0, y) float yM[20]; @@ -1883,7 +1804,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC auto yTransfer = yRTC->transferPixels(GrColorType::kAlpha_8, SkIRect::MakeWH(yRTC->width(), yRTC->height())); if (!yTransfer.fTransferBuffer) { - callback(context, nullptr); + callback(context, nullptr, nullptr); return; } @@ -1902,7 +1823,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC auto uTransfer = uRTC->transferPixels(GrColorType::kAlpha_8, SkIRect::MakeWH(uRTC->width(), uRTC->height())); if (!uTransfer.fTransferBuffer) { - callback(context, nullptr); + callback(context, nullptr, nullptr); return; } @@ -1920,15 +1841,14 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC auto vTransfer = vRTC->transferPixels(GrColorType::kAlpha_8, SkIRect::MakeWH(vRTC->width(), vRTC->height())); if (!vTransfer.fTransferBuffer) { - callback(context, nullptr); + callback(context, nullptr, nullptr); return; } struct FinishContext { - ReadPixelsCallback* fClientCallback; + ReadPixelsCallbackYUV420* fClientCallback; ReadPixelsContext fClientContext; - GrClientMappedBufferManager* fMappedBufferManager; - SkISize fSize; + int fW, fH; PixelTransferResult fYTransfer; PixelTransferResult fUTransfer; PixelTransferResult fVTransfer; @@ -1938,34 +1858,56 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC // callback to GrGpu until after the next flush that flushes our op list, though. auto* finishContext = new FinishContext{callback, context, - direct->priv().clientMappedBufferManager(), - dstSize, + dstW, + dstH, std::move(yTransfer), std::move(uTransfer), std::move(vTransfer)}; auto finishCallback = [](GrGpuFinishedContext c) { const auto* context = reinterpret_cast(c); - auto result = skstd::make_unique(context->fMappedBufferManager->inboxID()); - auto manager = context->fMappedBufferManager; - size_t rowBytes = SkToSizeT(context->fSize.width()); - if (!result->addTransferResult(context->fYTransfer, context->fSize, rowBytes, manager)) { - (*context->fClientCallback)(context->fClientContext, nullptr); + const void* y = context->fYTransfer.fTransferBuffer->map(); + const void* u = context->fUTransfer.fTransferBuffer->map(); + const void* v = context->fVTransfer.fTransferBuffer->map(); + if (!y || !u || !v) { + if (y) { + context->fYTransfer.fTransferBuffer->unmap(); + } + if (u) { + context->fUTransfer.fTransferBuffer->unmap(); + } + if (v) { + context->fVTransfer.fTransferBuffer->unmap(); + } + (*context->fClientCallback)(context->fClientContext, nullptr, 0); delete context; return; } - rowBytes /= 2; - SkISize uvSize = {context->fSize.width()/2, context->fSize.height()/2}; - if (!result->addTransferResult(context->fUTransfer, uvSize, rowBytes, manager)) { - (*context->fClientCallback)(context->fClientContext, nullptr); - delete context; - return; + size_t w = SkToSizeT(context->fW); + size_t h = SkToSizeT(context->fH); + std::unique_ptr yTemp; + if (context->fYTransfer.fPixelConverter) { + yTemp.reset(new uint8_t[w * h]); + context->fYTransfer.fPixelConverter(yTemp.get(), y); + y = yTemp.get(); } - if (!result->addTransferResult(context->fVTransfer, uvSize, rowBytes, manager)) { - (*context->fClientCallback)(context->fClientContext, nullptr); - delete context; - return; + std::unique_ptr uTemp; + if (context->fUTransfer.fPixelConverter) { + uTemp.reset(new uint8_t[w / 2 * h / 2]); + context->fUTransfer.fPixelConverter(uTemp.get(), u); + u = uTemp.get(); } - (*context->fClientCallback)(context->fClientContext, std::move(result)); + std::unique_ptr vTemp; + if (context->fVTransfer.fPixelConverter) { + vTemp.reset(new uint8_t[w / 2 * h / 2]); + context->fVTransfer.fPixelConverter(vTemp.get(), v); + v = vTemp.get(); + } + const void* data[] = {y, u, v}; + size_t rowBytes[] = {w, w / 2, w / 2}; + (*context->fClientCallback)(context->fClientContext, data, rowBytes); + context->fYTransfer.fTransferBuffer->unmap(); + context->fUTransfer.fTransferBuffer->unmap(); + context->fVTransfer.fTransferBuffer->unmap(); delete context; }; GrFlushInfo flushInfo; diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h index 0bb6525b90..1bc816558c 100644 --- a/src/gpu/GrRenderTargetContext.h +++ b/src/gpu/GrRenderTargetContext.h @@ -441,6 +441,7 @@ public: void drawDrawable(std::unique_ptr, const SkRect& bounds); using ReadPixelsCallback = SkSurface::ReadPixelsCallback; + using ReadPixelsCallbackYUV420 = SkSurface::ReadPixelsCallbackYUV420; using ReadPixelsContext = SkSurface::ReadPixelsContext; using RescaleGamma = SkSurface::RescaleGamma; @@ -450,12 +451,10 @@ public: ReadPixelsCallback callback, ReadPixelsContext context); // GPU implementation for SkSurface::asyncRescaleAndReadPixelsYUV420. void asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, - sk_sp dstColorSpace, - const SkIRect& srcRect, - const SkISize& dstSize, - RescaleGamma rescaleGamma, + sk_sp dstColorSpace, const SkIRect& srcRect, + int dstW, int dstH, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality, - ReadPixelsCallback callback, + ReadPixelsCallbackYUV420 callback, ReadPixelsContext context); /** @@ -623,8 +622,6 @@ private: bool SK_WARN_UNUSED_RESULT setupDstProxy(const GrClip&, const GrOp& op, GrXferProcessor::DstProxy* result); - class AsyncReadResult; - // The async read step of asyncRescaleAndReadPixels() void asyncReadPixels(const SkIRect& rect, SkColorType colorType, ReadPixelsCallback callback, ReadPixelsContext context); diff --git a/src/image/SkImage_Lazy.cpp b/src/image/SkImage_Lazy.cpp index c1ea2caf0f..898ee9129d 100644 --- a/src/image/SkImage_Lazy.cpp +++ b/src/image/SkImage_Lazy.cpp @@ -83,7 +83,7 @@ SkImage_Lazy::Validator::Validator(sk_sp gen, const SkIRect* su subset = &bounds; } - fInfo = info.makeDimensions(subset->size()); + fInfo = info.makeWH(subset->width(), subset->height()); fOrigin = SkIPoint::Make(subset->x(), subset->y()); if (colorType || colorSpace) { if (colorType) { @@ -321,7 +321,7 @@ sk_sp SkImage::DecodeToRaster(const void* encoded, size_t length, const if (!SkIRect::MakeWH(info.width(), info.height()).contains(*subset)) { return nullptr; } - info = info.makeDimensions(subset->size()); + info = info.makeWH(subset->width(), subset->height()); origin = {subset->x(), subset->y()}; } diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp index 5992af798d..f109234cf7 100644 --- a/src/image/SkImage_Raster.cpp +++ b/src/image/SkImage_Raster.cpp @@ -231,7 +231,7 @@ void SkImage_Raster::onUnpinAsTexture(GrContext* ctx) const { #endif sk_sp SkImage_Raster::onMakeSubset(GrRecordingContext*, const SkIRect& subset) const { - SkImageInfo info = fBitmap.info().makeDimensions(subset.size()); + SkImageInfo info = fBitmap.info().makeWH(subset.width(), subset.height()); SkBitmap bitmap; if (!bitmap.tryAllocPixels(info)) { return nullptr; diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp index a04982dc51..c8b6e79246 100644 --- a/src/image/SkSurface.cpp +++ b/src/image/SkSurface.cpp @@ -12,7 +12,6 @@ #include "include/gpu/GrBackendSurface.h" #include "src/core/SkAutoPixmapStorage.h" #include "src/core/SkImagePriv.h" -#include "src/core/SkMakeUnique.h" #include "src/image/SkSurface_Base.h" static SkPixelGeometry compute_default_geometry() { @@ -145,7 +144,7 @@ void SkSurface_Base::onAsyncRescaleAndReadPixels(const SkImageInfo& info, const ii = ii.makeColorType(this->getCanvas()->imageInfo().colorType()); linearSurf = this->makeSurface(ii); if (!linearSurf) { - callback(context, nullptr); + callback(context, nullptr, 0); return; } } @@ -183,7 +182,7 @@ void SkSurface_Base::onAsyncRescaleAndReadPixels(const SkImageInfo& info, const } auto next = this->makeSurface(ii); if (!next) { - callback(context, nullptr); + callback(context, nullptr, 0); return; } next->getCanvas()->drawImageRect( @@ -196,35 +195,22 @@ void SkSurface_Base::onAsyncRescaleAndReadPixels(const SkImageInfo& info, const constraint = SkCanvas::kFast_SrcRectConstraint; } - size_t rowBytes = info.minRowBytes(); - std::unique_ptr data(new char[info.height() * rowBytes]); - SkPixmap pm(info, data.get(), rowBytes); + SkAutoPixmapStorage pm; + pm.alloc(info); if (src->readPixels(pm, srcX, srcY)) { - class Result : public AsyncReadResult { - public: - Result(std::unique_ptr data, size_t rowBytes) - : fData(std::move(data)), fRowBytes(rowBytes) {} - int count() const override { return 1; } - const void* data(int i) const override { return fData.get(); } - size_t rowBytes(int i) const override { return fRowBytes; } - - private: - std::unique_ptr fData; - size_t fRowBytes; - }; - callback(context, skstd::make_unique(std::move(data), rowBytes)); + callback(context, pm.addr(), pm.rowBytes()); } else { - callback(context, nullptr); + callback(context, nullptr, 0); } } void SkSurface_Base::onAsyncRescaleAndReadPixelsYUV420( SkYUVColorSpace yuvColorSpace, sk_sp dstColorSpace, const SkIRect& srcRect, - const SkISize& dstSize, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality, - ReadPixelsCallback callback, ReadPixelsContext context) { + int dstW, int dstH, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality, + ReadPixelsCallbackYUV420 callback, ReadPixelsContext context) { // TODO: Call non-YUV asyncRescaleAndReadPixels and then make our callback convert to YUV and // call client's callback. - callback(context, nullptr); + callback(context, nullptr, nullptr); } bool SkSurface_Base::outstandingImageSnapshot() const { @@ -361,119 +347,30 @@ bool SkSurface::readPixels(const SkBitmap& bitmap, int srcX, int srcY) { return bitmap.peekPixels(&pm) && this->readPixels(pm, srcX, srcY); } -// Stuff to keep the legacy async readback APIs working on top of the new implementation. -namespace { -struct BridgeContext { - SkSurface::ReadPixelsContext fClientContext; - SkSurface::LegacyReadPixelsCallback* fClientCallback; -}; -struct BridgeContextYUV420 { - SkSurface::ReadPixelsContext fClientContext; - SkSurface::LegacyReadPixelsCallbackYUV420* fClientCallback; -}; -} // anonymous namespace - -static void bridge_callback(SkSurface::ReadPixelsContext context, - std::unique_ptr result) { - auto bridgeContext = static_cast(context); - if (!result || result->count() != 1) { - bridgeContext->fClientCallback(bridgeContext->fClientContext, nullptr, 0); - } else { - bridgeContext->fClientCallback(bridgeContext->fClientContext, result->data(0), - result->rowBytes(0)); - } - delete bridgeContext; -} - -static void bridge_callback_yuv420(SkSurface::ReadPixelsContext context, - std::unique_ptr result) { - auto bridgeContext = static_cast(context); - if (!result || result->count() != 3) { - bridgeContext->fClientCallback(bridgeContext->fClientContext, nullptr, 0); - } else { - const void* data[] = {result->data(0), result->data(1), result->data(2)}; - size_t rowBytes[] = {result->rowBytes(0), result->rowBytes(1), result->rowBytes(2)}; - bridgeContext->fClientCallback(bridgeContext->fClientContext, data, rowBytes); - } - delete bridgeContext; -} - -void SkSurface::asyncRescaleAndReadPixels(const SkImageInfo& info, - const SkIRect& srcRect, - RescaleGamma rescaleGamma, - SkFilterQuality rescaleQuality, - LegacyReadPixelsCallback callback, - ReadPixelsContext context) { +void SkSurface::asyncRescaleAndReadPixels(const SkImageInfo& info, const SkIRect& srcRect, + RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality, + ReadPixelsCallback callback, ReadPixelsContext context) { if (!SkIRect::MakeWH(this->width(), this->height()).contains(srcRect) || !SkImageInfoIsValid(info)) { callback(context, nullptr, 0); return; } - - auto bridgeContext = new BridgeContext{context, callback}; - asSB(this)->onAsyncRescaleAndReadPixels(info, srcRect, rescaleGamma, rescaleQuality, - bridge_callback, bridgeContext); + asSB(this)->onAsyncRescaleAndReadPixels(info, srcRect, rescaleGamma, rescaleQuality, callback, + context); } -void SkSurface::asyncRescaleAndReadPixels(const SkImageInfo& info, - const SkIRect& srcRect, - RescaleGamma rescaleGamma, - SkFilterQuality rescaleQuality, - ReadPixelsCallback callback, - ReadPixelsContext context) { - if (!SkIRect::MakeWH(this->width(), this->height()).contains(srcRect) || - !SkImageInfoIsValid(info)) { - callback(context, nullptr); - return; - } - asSB(this)->onAsyncRescaleAndReadPixels( - info, srcRect, rescaleGamma, rescaleQuality, callback, context); -} - -void SkSurface::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, - sk_sp dstColorSpace, - const SkIRect& srcRect, - int dstW, int dstH, - RescaleGamma rescaleGamma, - SkFilterQuality rescaleQuality, - LegacyReadPixelsCallbackYUV420 callback, - ReadPixelsContext context) { +void SkSurface::asyncRescaleAndReadPixelsYUV420( + SkYUVColorSpace yuvColorSpace, sk_sp dstColorSpace, const SkIRect& srcRect, + int dstW, int dstH, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality, + ReadPixelsCallbackYUV420 callback, ReadPixelsContext context) { if (!SkIRect::MakeWH(this->width(), this->height()).contains(srcRect) || (dstW & 0b1) || (dstH & 0b1)) { callback(context, nullptr, nullptr); return; } - auto bridgeContext = new BridgeContextYUV420{context, callback}; - asSB(this)->onAsyncRescaleAndReadPixelsYUV420(yuvColorSpace, - std::move(dstColorSpace), srcRect, - {dstW, dstH}, - rescaleGamma, - rescaleQuality, - bridge_callback_yuv420, - bridgeContext); -} - -void SkSurface::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, - sk_sp dstColorSpace, - const SkIRect& srcRect, - const SkISize& dstSize, - RescaleGamma rescaleGamma, - SkFilterQuality rescaleQuality, - ReadPixelsCallback callback, - ReadPixelsContext context) { - if (!SkIRect::MakeWH(this->width(), this->height()).contains(srcRect) || dstSize.isZero() || - (dstSize.width() & 0b1) || (dstSize.height() & 0b1)) { - callback(context, nullptr); - return; - } - asSB(this)->onAsyncRescaleAndReadPixelsYUV420(yuvColorSpace, - std::move(dstColorSpace), - srcRect, - dstSize, - rescaleGamma, - rescaleQuality, - callback, - context); + asSB(this)->onAsyncRescaleAndReadPixelsYUV420(yuvColorSpace, std::move(dstColorSpace), srcRect, + dstW, dstH, rescaleGamma, rescaleQuality, + callback, context); } void SkSurface::writePixels(const SkPixmap& pmap, int x, int y) { diff --git a/src/image/SkSurface_Base.h b/src/image/SkSurface_Base.h index 7bff9a87e9..460f5a844c 100644 --- a/src/image/SkSurface_Base.h +++ b/src/image/SkSurface_Base.h @@ -51,23 +51,21 @@ public: /** * Default implementation does a rescale/read and then calls the callback. */ - virtual void onAsyncRescaleAndReadPixels(const SkImageInfo&, - const SkIRect& srcRect, - RescaleGamma, - SkFilterQuality, - ReadPixelsCallback, - ReadPixelsContext); + virtual void onAsyncRescaleAndReadPixels(const SkImageInfo& info, const SkIRect& srcRect, + RescaleGamma rescaleGamma, + SkFilterQuality rescaleQuality, + ReadPixelsCallback callback, + ReadPixelsContext context); /** * Default implementation does a rescale/read/yuv conversion and then calls the callback. */ - virtual void onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace, + virtual void onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, sk_sp dstColorSpace, - const SkIRect& srcRect, - const SkISize& dstSize, - RescaleGamma, - SkFilterQuality, - ReadPixelsCallback, - ReadPixelsContext); + const SkIRect& srcRect, int dstW, int dstH, + RescaleGamma rescaleGamma, + SkFilterQuality rescaleQuality, + ReadPixelsCallbackYUV420 callback, + ReadPixelsContext context); /** * Default implementation: diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp index 6eb3fda7fe..56ce90ab9e 100644 --- a/src/image/SkSurface_Gpu.cpp +++ b/src/image/SkSurface_Gpu.cpp @@ -132,8 +132,7 @@ void SkSurface_Gpu::onWritePixels(const SkPixmap& src, int x, int y) { fDevice->writePixels(src, x, y); } -void SkSurface_Gpu::onAsyncRescaleAndReadPixels(const SkImageInfo& info, - const SkIRect& srcRect, +void SkSurface_Gpu::onAsyncRescaleAndReadPixels(const SkImageInfo& info, const SkIRect& srcRect, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality, ReadPixelsCallback callback, @@ -142,23 +141,13 @@ void SkSurface_Gpu::onAsyncRescaleAndReadPixels(const SkImageInfo& info, rtc->asyncRescaleAndReadPixels(info, srcRect, rescaleGamma, rescaleQuality, callback, context); } -void SkSurface_Gpu::onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, - sk_sp dstColorSpace, - const SkIRect& srcRect, - const SkISize& dstSize, - RescaleGamma rescaleGamma, - SkFilterQuality rescaleQuality, - ReadPixelsCallback callback, - ReadPixelsContext context) { +void SkSurface_Gpu::onAsyncRescaleAndReadPixelsYUV420( + SkYUVColorSpace yuvColorSpace, sk_sp dstColorSpace, const SkIRect& srcRect, + int dstW, int dstH, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality, + ReadPixelsCallbackYUV420 callback, ReadPixelsContext context) { auto* rtc = this->fDevice->accessRenderTargetContext(); - rtc->asyncRescaleAndReadPixelsYUV420(yuvColorSpace, - std::move(dstColorSpace), - srcRect, - dstSize, - rescaleGamma, - rescaleQuality, - callback, - context); + rtc->asyncRescaleAndReadPixelsYUV420(yuvColorSpace, std::move(dstColorSpace), srcRect, dstW, + dstH, rescaleGamma, rescaleQuality, callback, context); } // Create a new render target and, if necessary, copy the contents of the old diff --git a/src/image/SkSurface_Gpu.h b/src/image/SkSurface_Gpu.h index e27e7e5df1..c1768111bb 100644 --- a/src/image/SkSurface_Gpu.h +++ b/src/image/SkSurface_Gpu.h @@ -40,11 +40,10 @@ public: ReadPixelsContext context) override; void onAsyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, sk_sp dstColorSpace, - const SkIRect& srcRect, - const SkISize& dstSize, + const SkIRect& srcRect, int dstW, int dstH, RescaleGamma rescaleGamma, SkFilterQuality rescaleQuality, - ReadPixelsCallback callback, + ReadPixelsCallbackYUV420 callback, ReadPixelsContext context) override; void onCopyOnWrite(ContentChangeMode) override; diff --git a/src/image/SkSurface_Raster.cpp b/src/image/SkSurface_Raster.cpp index a086165ea4..f6e4c4f161 100644 --- a/src/image/SkSurface_Raster.cpp +++ b/src/image/SkSurface_Raster.cpp @@ -111,7 +111,7 @@ sk_sp SkSurface_Raster::onNewImageSnapshot(const SkIRect* subset) { if (subset) { SkASSERT(SkIRect::MakeWH(fBitmap.width(), fBitmap.height()).contains(*subset)); SkBitmap dst; - dst.allocPixels(fBitmap.info().makeDimensions(subset->size())); + dst.allocPixels(fBitmap.info().makeWH(subset->width(), subset->height())); SkAssertResult(fBitmap.readPixels(dst.pixmap(), subset->left(), subset->top())); dst.setImmutable(); // key, so MakeFromBitmap doesn't make a copy of the buffer return SkImage::MakeFromBitmap(dst); diff --git a/tests/AndroidCodecTest.cpp b/tests/AndroidCodecTest.cpp index 2c690f7fd1..f8496918d1 100644 --- a/tests/AndroidCodecTest.cpp +++ b/tests/AndroidCodecTest.cpp @@ -291,7 +291,7 @@ DEF_TEST(AndroidCodec_sampledOrientation, r) { options.fSampleSize = sampleSize; SkBitmap bm; - auto info = androidCodec->getInfo().makeDimensions(sampledDims); + auto info = androidCodec->getInfo().makeWH(sampledDims.width(), sampledDims.height()); bm.allocPixels(info); auto result = androidCodec->getAndroidPixels(info, bm.getPixels(), bm.rowBytes(), &options); diff --git a/tests/BitmapCopyTest.cpp b/tests/BitmapCopyTest.cpp index e960df805b..cb693aa2f9 100644 --- a/tests/BitmapCopyTest.cpp +++ b/tests/BitmapCopyTest.cpp @@ -192,7 +192,8 @@ DEF_TEST(BitmapReadPixels, reporter) { for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { clear_4x4_pixels(dstPixels); - dstInfo = dstInfo.makeDimensions(gRec[i].fRequestedDstSize); + dstInfo = dstInfo.makeWH(gRec[i].fRequestedDstSize.width(), + gRec[i].fRequestedDstSize.height()); bool success = srcBM.readPixels(dstInfo, dstPixels, rowBytes, gRec[i].fRequestedSrcLoc.x(), gRec[i].fRequestedSrcLoc.y()); diff --git a/tests/CodecAnimTest.cpp b/tests/CodecAnimTest.cpp index 6e895f74e4..40cad818a2 100644 --- a/tests/CodecAnimTest.cpp +++ b/tests/CodecAnimTest.cpp @@ -415,7 +415,7 @@ DEF_TEST(AndroidCodec_animated, r) { for (int sampleSize : { 8, 32, 100 }) { auto dimensions = codec->codec()->getScaledDimensions(1.0f / sampleSize); - info = info.makeDimensions(dimensions); + info = info.makeWH(dimensions.width(), dimensions.height()); SkBitmap bm; bm.allocPixels(info); diff --git a/tests/CodecTest.cpp b/tests/CodecTest.cpp index f597e062d8..23db4a978f 100644 --- a/tests/CodecTest.cpp +++ b/tests/CodecTest.cpp @@ -407,7 +407,7 @@ static void check(skiatest::Reporter* r, const bool supported = codec->getValidSubset(&subset); REPORTER_ASSERT(r, supported == supportsSubsetDecoding); - SkImageInfo subsetInfo = info.makeDimensions(subset.size()); + SkImageInfo subsetInfo = info.makeWH(subset.width(), subset.height()); SkBitmap bm; bm.allocPixels(subsetInfo); const auto result = codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes(), &opts); @@ -594,7 +594,7 @@ static void test_dimensions(skiatest::Reporter* r, const char path[]) { // Scale the output dimensions SkISize scaledDims = codec->getSampledDimensions(sampleSize); SkImageInfo scaledInfo = codec->getInfo() - .makeDimensions(scaledDims) + .makeWH(scaledDims.width(), scaledDims.height()) .makeColorType(kN32_SkColorType); // Set up for the decode @@ -1335,7 +1335,7 @@ DEF_TEST(Codec_reusePng, r) { SkAndroidCodec::AndroidOptions opts; opts.fSampleSize = 5; auto size = codec->getSampledDimensions(opts.fSampleSize); - auto info = codec->getInfo().makeDimensions(size).makeColorType(kN32_SkColorType); + auto info = codec->getInfo().makeWH(size.fWidth, size.fHeight).makeColorType(kN32_SkColorType); SkBitmap bm; bm.allocPixels(info); auto result = codec->getAndroidPixels(info, bm.getPixels(), bm.rowBytes(), &opts); @@ -1709,7 +1709,7 @@ DEF_TEST(Codec_78329453, r) { // but the ones tested by DM happen to not. constexpr int kSampleSize = 19; const auto size = codec->getSampledDimensions(kSampleSize); - auto info = codec->getInfo().makeDimensions(size); + auto info = codec->getInfo().makeWH(size.width(), size.height()); SkBitmap bm; bm.allocPixels(info); bm.eraseColor(SK_ColorTRANSPARENT); diff --git a/tests/ReadPixelsTest.cpp b/tests/ReadPixelsTest.cpp index d182b24b67..f80748d9a1 100644 --- a/tests/ReadPixelsTest.cpp +++ b/tests/ReadPixelsTest.cpp @@ -645,33 +645,16 @@ static int min_rgb_channel_bits(SkColorType ct) { SK_ABORT("Unexpected color type."); } -namespace { -struct AsyncContext { - bool fCalled = false; - std::unique_ptr fResult; -}; -} // anonymous namespace - -// Making this a lambda in the test functions caused: -// "error: cannot compile this forwarded non-trivially copyable parameter yet" -// on x86/Win/Clang bot, referring to 'result'. -static void async_callback(void* c, std::unique_ptr result) { - auto context = static_cast(c); - context->fResult = std::move(result); - context->fCalled = true; -}; - DEF_GPUTEST_FOR_RENDERING_CONTEXTS(AsyncReadPixels, reporter, ctxInfo) { - struct LegacyContext { + struct Context { SkPixmap* fPixmap = nullptr; bool fSuceeded = false; bool fCalled = false; }; - auto legacy_callback = [](SkSurface::ReleaseContext context, const void* data, - size_t rowBytes) { - auto* pm = static_cast(context)->fPixmap; - static_cast(context)->fCalled = true; - if ((static_cast(context)->fSuceeded = SkToBool(data))) { + auto callback = [](SkSurface::ReleaseContext context, const void* data, size_t rowBytes) { + auto* pm = static_cast(context)->fPixmap; + static_cast(context)->fCalled = true; + if ((static_cast(context)->fSuceeded = SkToBool(data))) { auto dst = static_cast(pm->writable_addr()); const auto* src = static_cast(data); for (int y = 0; y < pm->height(); ++y, src += rowBytes, dst += pm->rowBytes()) { @@ -720,222 +703,76 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(AsyncReadPixels, reporter, ctxInfo) { SkIRect::MakeLTRB(1, 2, kW - 3, kH - 4), SkIRect::MakeXYWH(1, 1, 0, 0), SkIRect::MakeWH(kW + 1, kH / 2)}) { - for (bool legacy : {false, true}) { - SkPixmap result; - std::unique_ptr tempPixels; - info = SkImageInfo::Make(rect.size(), readCT, kPremul_SkAlphaType, - readCS); - // Rescale quality and linearity don't matter since we're doing a non- - // scaling readback. - static constexpr auto kQuality = kNone_SkFilterQuality; - static constexpr auto kGamma = SkSurface::RescaleGamma::kSrc; - bool succeeded = false; - // This holds the pixel results and so must live until comparisons are - // finished. - AsyncContext asyncContext; - if (legacy) { - LegacyContext context; - tempPixels.reset(new char[info.computeMinByteSize()]); - result.reset(info, tempPixels.get(), info.minRowBytes()); - memset(result.writable_addr(), 0xAB, info.computeMinByteSize()); - context.fPixmap = &result; - surf->asyncRescaleAndReadPixels(info, rect, kGamma, kQuality, - legacy_callback, &context); - while (!context.fCalled) { - ctxInfo.grContext()->checkAsyncWorkCompletion(); - } - succeeded = context.fSuceeded; - } else { - surf->asyncRescaleAndReadPixels(info, rect, kGamma, kQuality, - async_callback, &asyncContext); - while (!asyncContext.fCalled) { - ctxInfo.grContext()->checkAsyncWorkCompletion(); - } - if (asyncContext.fResult) { - int count = asyncContext.fResult->count(); - if (count == 1) { - succeeded = true; - result.reset(info, - asyncContext.fResult->data(0), - asyncContext.fResult->rowBytes(0)); - } else { - ERRORF(reporter, "Unexpected AsyncResult::count(): %d", - count); - continue; - } - } - } - - if (rect.isEmpty() || !SkIRect::MakeWH(kW, kH).contains(rect)) { - REPORTER_ASSERT(reporter, !succeeded); - } - - bool didCSConversion = !SkColorSpace::Equals( - readCS.get(), surf->imageInfo().colorSpace()); - - if (succeeded) { - REPORTER_ASSERT(reporter, - readCT != kUnknown_SkColorType && !rect.isEmpty()); - } else { - // TODO: Support reading to kGray, support kRGB_101010x at all in - // GPU. - auto surfBounds = SkIRect::MakeWH(surf->width(), surf->height()); - if (readCT != kUnknown_SkColorType && - readCT != kGray_8_SkColorType && - readCT != kRGB_101010x_SkColorType && !rect.isEmpty() && - surfBounds.contains(rect)) { - ERRORF(reporter, - "Async read failed. Surf Color Type: %s, Read CT: %s," - "Rect [%d, %d, %d, %d], origin: %d, CS conversion: %d\n", - ToolUtils::colortype_name(surfCT), - ToolUtils::colortype_name(readCT), rect.fLeft, rect.fTop, - rect.fRight, rect.fBottom, origin, didCSConversion); - } - continue; - } - SkPixmap ref; - refImg->peekPixels(&ref); - SkAssertResult(ref.extractSubset(&ref, rect)); - - // A CS conversion allows a 3 value difference and otherwise a 2 value - // difference. Note that sometimes read back on GPU can be lossy even - // when there no conversion at all because GPU->CPU read may go to a - // lower bit depth format and then be promoted back to the original - // type. For example, GL ES cannot read to 1010102, so we go through - // 8888. - float numer = didCSConversion ? 3.f : 2.f; - int rgbBits = std::min({min_rgb_channel_bits(readCT), - min_rgb_channel_bits(surfCT), 8}); - float tol = numer / (1 << rgbBits); - const float tols[4] = {tol, tol, tol, 0}; - auto error = std::function< - ComparePixmapsErrorReporter>([&](int x, int y, - const float diffs[4]) { - SkASSERT(x >= 0 && y >= 0); - ERRORF(reporter, - "Surf Color Type: %s, Read CT: %s, Rect [%d, %d, %d, %d]" - ", origin: %d, CS conversion: %d\n" - "Error at %d, %d. Diff in floats: (%f, %f, %f %f)", - ToolUtils::colortype_name(surfCT), - ToolUtils::colortype_name(readCT), rect.fLeft, rect.fTop, - rect.fRight, rect.fBottom, origin, didCSConversion, x, y, - diffs[0], diffs[1], diffs[2], diffs[3]); - }); - compare_pixels(ref, result, tols, error); + SkAutoPixmapStorage result; + Context context; + context.fPixmap = &result; + info = SkImageInfo::Make(rect.size(), readCT, kPremul_SkAlphaType, readCS); + result.alloc(info); + memset(result.writable_addr(), 0xAB, result.computeByteSize()); + // Rescale quality and linearity don't matter since we're doing a non- + // scaling readback. + surf->asyncRescaleAndReadPixels(info, rect, SkSurface::RescaleGamma::kSrc, + kNone_SkFilterQuality, callback, &context); + while (!context.fCalled) { + ctxInfo.grContext()->checkAsyncWorkCompletion(); } + if (rect.isEmpty() || !SkIRect::MakeWH(kW, kH).contains(rect)) { + REPORTER_ASSERT(reporter, !context.fSuceeded); + } + + bool didCSConversion = + !SkColorSpace::Equals(readCS.get(), surf->imageInfo().colorSpace()); + + if (context.fSuceeded) { + REPORTER_ASSERT(reporter, readCT != kUnknown_SkColorType && + !rect.isEmpty()); + } else { + // TODO: Support reading to kGray, support kRGB_101010x at all in GPU. + auto surfBounds = SkIRect::MakeWH(surf->width(), surf->height()); + if (readCT != kUnknown_SkColorType && readCT != kGray_8_SkColorType && + readCT != kRGB_101010x_SkColorType && !rect.isEmpty() && + surfBounds.contains(rect)) { + ERRORF(reporter, + "Async read failed. Surf Color Type: %s, Read CT: %s," + "Rect [%d, %d, %d, %d], origin: %d, CS conversion: %d\n", + ToolUtils::colortype_name(surfCT), + ToolUtils::colortype_name(readCT), + rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, origin, + didCSConversion); + } + continue; + } + SkPixmap ref; + refImg->peekPixels(&ref); + SkAssertResult(ref.extractSubset(&ref, rect)); + + // A CS conversion allows a 3 value difference and otherwise a 2 value + // difference. Note that sometimes read back on GPU can be lossy even when + // there no conversion at all because GPU->CPU read may go to a a lower bit + // depth format and then be promoted back to the original type. For example, + // GL ES cannot read to 1010102, so we go through 8888. + float numer = didCSConversion ? 3.f : 2.f; + int rgbBits = std::min({min_rgb_channel_bits(readCT), + min_rgb_channel_bits(surfCT), 8}); + float tol = numer / (1 << rgbBits); + const float tols[4] = {tol, tol, tol, 0}; + auto error = std::function( + [&](int x, int y, const float diffs[4]) { + SkASSERT(x >= 0 && y >= 0); + ERRORF(reporter, + "Surf Color Type: %s, Read CT: %s, Rect [%d, %d, %d, %d]" + ", origin: %d, CS conversion: %d\n" + "Error at %d, %d. Diff in floats: (%f, %f, %f %f)", + ToolUtils::colortype_name(surfCT), + ToolUtils::colortype_name(readCT), + rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, origin, + didCSConversion, x, y, diffs[0], diffs[1], diffs[2], + diffs[3]); + }); + compare_pixels(ref, result, tols, error); } } } } } } - -DEF_GPUTEST(AsyncReadPixelsContextShutdown, reporter, options) { - const auto ii = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType, - SkColorSpace::MakeSRGB()); - enum class ShutdownSequence { - kFreeResult_DestroyContext, - kDestroyContext_FreeResult, - kFreeResult_ReleaseAndAbandon_DestroyContext, - kFreeResult_Abandon_DestroyContext, - kReleaseAndAbandon_FreeResult_DestroyContext, - kAbandon_FreeResult_DestroyContext, - kReleaseAndAbandon_DestroyContext_FreeResult, - kAbandon_DestroyContext_FreeResult, - }; - for (int t = 0; t < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++t) { - auto type = static_cast(t); - for (auto sequence : {ShutdownSequence::kFreeResult_DestroyContext, - ShutdownSequence::kDestroyContext_FreeResult, - ShutdownSequence::kFreeResult_ReleaseAndAbandon_DestroyContext, - ShutdownSequence::kFreeResult_Abandon_DestroyContext, - ShutdownSequence::kReleaseAndAbandon_FreeResult_DestroyContext, - ShutdownSequence::kAbandon_FreeResult_DestroyContext, - ShutdownSequence::kReleaseAndAbandon_DestroyContext_FreeResult, - ShutdownSequence::kAbandon_DestroyContext_FreeResult}) { - // Vulkan context abandoning without resource release has issues outside of the scope of - // this test. - if (type == sk_gpu_test::GrContextFactory::kVulkan_ContextType && - (sequence == ShutdownSequence::kAbandon_FreeResult_DestroyContext || - sequence == ShutdownSequence::kAbandon_DestroyContext_FreeResult || - sequence == ShutdownSequence::kFreeResult_Abandon_DestroyContext)) { - continue; - } - for (bool yuv : {false, true}) { - sk_gpu_test::GrContextFactory factory(options); - auto context = factory.get(type); - if (!context) { - continue; - } - // This test is only meaningful for contexts that support transfer buffers. - if (!context->priv().caps()->transferBufferSupport()) { - continue; - } - auto surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, ii, 1, nullptr); - if (!surf) { - continue; - } - AsyncContext cbContext; - if (yuv) { - surf->asyncRescaleAndReadPixelsYUV420( - kIdentity_SkYUVColorSpace, SkColorSpace::MakeSRGB(), ii.bounds(), - ii.dimensions(), SkSurface::RescaleGamma::kSrc, kNone_SkFilterQuality, - &async_callback, &cbContext); - } else { - surf->asyncRescaleAndReadPixels(ii, ii.bounds(), SkSurface::RescaleGamma::kSrc, - kNone_SkFilterQuality, &async_callback, - &cbContext); - } - while (!cbContext.fCalled) { - context->checkAsyncWorkCompletion(); - } - if (!cbContext.fResult) { - ERRORF(reporter, "Callback failed on %s. is YUV: %d", - sk_gpu_test::GrContextFactory::ContextTypeName(type), yuv); - continue; - } - // The real test is that we don't crash, get Vulkan validation errors, etc, during - // this shutdown sequence. - switch (sequence) { - case ShutdownSequence::kFreeResult_DestroyContext: - case ShutdownSequence::kFreeResult_ReleaseAndAbandon_DestroyContext: - case ShutdownSequence::kFreeResult_Abandon_DestroyContext: - break; - case ShutdownSequence::kDestroyContext_FreeResult: - factory.destroyContexts(); - break; - case ShutdownSequence::kReleaseAndAbandon_FreeResult_DestroyContext: - factory.releaseResourcesAndAbandonContexts(); - break; - case ShutdownSequence::kAbandon_FreeResult_DestroyContext: - factory.abandonContexts(); - break; - case ShutdownSequence::kReleaseAndAbandon_DestroyContext_FreeResult: - factory.releaseResourcesAndAbandonContexts(); - factory.destroyContexts(); - break; - case ShutdownSequence::kAbandon_DestroyContext_FreeResult: - factory.abandonContexts(); - factory.destroyContexts(); - break; - } - cbContext.fResult.reset(); - switch (sequence) { - case ShutdownSequence::kFreeResult_ReleaseAndAbandon_DestroyContext: - factory.releaseResourcesAndAbandonContexts(); - break; - case ShutdownSequence::kFreeResult_Abandon_DestroyContext: - factory.abandonContexts(); - break; - case ShutdownSequence::kFreeResult_DestroyContext: - case ShutdownSequence::kDestroyContext_FreeResult: - case ShutdownSequence::kReleaseAndAbandon_FreeResult_DestroyContext: - case ShutdownSequence::kAbandon_FreeResult_DestroyContext: - case ShutdownSequence::kReleaseAndAbandon_DestroyContext_FreeResult: - case ShutdownSequence::kAbandon_DestroyContext_FreeResult: - break; - } - } - } - } -} diff --git a/tools/fm/fm.cpp b/tools/fm/fm.cpp index d89bcac2d0..65a9c9339e 100644 --- a/tools/fm/fm.cpp +++ b/tools/fm/fm.cpp @@ -143,7 +143,8 @@ static void init(Source* source, std::shared_ptr codec) { source->draw = [codec](SkCanvas* canvas) { SkImageInfo info = codec->getInfo(); if (FLAGS_decodeToDst) { - info = canvas->imageInfo().makeDimensions(info.dimensions()); + info = canvas->imageInfo().makeWH(info.width(), + info.height()); } SkBitmap bm; @@ -499,7 +500,8 @@ int main(int argc, char** argv) { fprintf(stdout, "%50s", source.name.c_str()); fflush(stdout); - const SkImageInfo info = unsized_info.makeDimensions(source.size); + const SkImageInfo info = unsized_info.makeWH(source.size.width(), + source.size.height()); auto draw = [&source](SkCanvas* canvas) { Result result = source.draw(canvas);