diff options
author | 2016-03-07 12:45:14 -0800 | |
---|---|---|
committer | 2016-03-07 12:45:14 -0800 | |
commit | 4418dbac3386f26c8da62ab242be9c178961eb18 (patch) | |
tree | d94be5d8f77cb85fd6bc908ef7ebc93357ce4908 /src/core | |
parent | 19de504eaee0c18cac4f840e0ca336a1e41b65eb (diff) |
Swap over to using SkImageFilter::filterImage instead of filterImageDeprecated
This CL relies on https://codereview.chromium.org/1757983002/ (Add SkSpecialImage-based methods to SkImageFilter)
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1762013002
TBR=bsalomon@google.com
Review URL: https://codereview.chromium.org/1762013002
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkCanvas.cpp | 23 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 17 | ||||
-rw-r--r-- | src/core/SkImageFilter.cpp | 72 | ||||
-rw-r--r-- | src/core/SkSpecialImage.cpp | 51 | ||||
-rw-r--r-- | src/core/SkSpecialImage.h | 17 |
5 files changed, 139 insertions, 41 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index f3f38386bd..35710fb317 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -28,6 +28,7 @@ #include "SkReadPixelsRec.h" #include "SkRRect.h" #include "SkSmallAllocator.h" +#include "SkSpecialImage.h" #include "SkSurface_Base.h" #include "SkTextBlob.h" #include "SkTextFormatParams.h" @@ -1392,19 +1393,29 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, SkIPoint pos = { x - iter.getX(), y - iter.getY() }; if (filter && !dstDev->canHandleImageFilter(filter)) { SkImageFilter::DeviceProxy proxy(dstDev); - SkBitmap dst; SkIPoint offset = SkIPoint::Make(0, 0); - const SkBitmap& src = srcDev->accessBitmap(false); + const SkBitmap& srcBM = srcDev->accessBitmap(false); SkMatrix matrix = *iter.fMatrix; matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y())); - SkIRect clipBounds = iter.fClip->getBounds().makeOffset(-pos.x(), -pos.y()); + const SkIRect clipBounds = iter.fClip->getBounds().makeOffset(-pos.x(), -pos.y()); SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache()); SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); - if (filter->filterImageDeprecated(&proxy, src, ctx, &dst, &offset)) { + + SkAutoTUnref<SkSpecialImage> srcImg(SkSpecialImage::internal_fromBM(&proxy, srcBM)); + if (!srcImg) { + continue; // something disastrous happened + } + + SkAutoTUnref<SkSpecialImage> resultImg(filter->filterImage(srcImg, ctx, &offset)); + if (resultImg) { SkPaint tmpUnfiltered(*paint); tmpUnfiltered.setImageFilter(nullptr); - dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), - tmpUnfiltered); + SkBitmap resultBM; + if (resultImg->internal_getBM(&resultBM)) { + // TODO: add drawSprite(SkSpecialImage) to SkDevice? (see skbug.com/5073) + dstDev->drawSprite(iter, resultBM, pos.x() + offset.x(), pos.y() + offset.y(), + tmpUnfiltered); + } } } else if (deviceIsBitmapDevice) { const SkBitmap& src = static_cast<SkBitmapDevice*>(srcDev)->fBitmap; diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 7adb0f4b3c..fa4a4b8fd1 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -17,6 +17,7 @@ #include "SkRasterClip.h" #include "SkRSXform.h" #include "SkShader.h" +#include "SkSpecialImage.h" #include "SkTextBlobRunIterator.h" #include "SkTextToPathIter.h" @@ -408,17 +409,27 @@ void SkBaseDevice::drawBitmapAsSprite(const SkDraw& draw, const SkBitmap& bitmap SkImageFilter* filter = paint.getImageFilter(); if (filter && !this->canHandleImageFilter(filter)) { SkImageFilter::DeviceProxy proxy(this); - SkBitmap dst; SkIPoint offset = SkIPoint::Make(0, 0); SkMatrix matrix = *draw.fMatrix; matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); const SkIRect clipBounds = draw.fClip->getBounds().makeOffset(-x, -y); SkAutoTUnref<SkImageFilter::Cache> cache(this->getImageFilterCache()); SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); - if (filter->filterImageDeprecated(&proxy, bitmap, ctx, &dst, &offset)) { + + SkAutoTUnref<SkSpecialImage> srcImg(SkSpecialImage::internal_fromBM(&proxy, bitmap)); + if (!srcImg) { + return; // something disastrous happened + } + + SkAutoTUnref<SkSpecialImage> resultImg(filter->filterImage(srcImg, ctx, &offset)); + if (resultImg) { SkPaint tmpUnfiltered(paint); tmpUnfiltered.setImageFilter(nullptr); - this->drawSprite(draw, dst, x + offset.x(), y + offset.y(), tmpUnfiltered); + SkBitmap resultBM; + if (resultImg->internal_getBM(&resultBM)) { + // TODO: add drawSprite(SkSpecialImage) to SkDevice? (see skbug.com/5073) + this->drawSprite(draw, resultBM, x + offset.x(), y + offset.y(), tmpUnfiltered); + } } } else { this->drawSprite(draw, bitmap, x, y, paint); diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp index 5f905285bb..a233871bff 100644 --- a/src/core/SkImageFilter.cpp +++ b/src/core/SkImageFilter.cpp @@ -272,7 +272,20 @@ bool SkImageFilter::filterInputDeprecated(int index, Proxy* proxy, const SkBitma if (!input) { return true; } - return input->filterImageDeprecated(proxy, src, this->mapContext(ctx), result, offset); + + SkAutoTUnref<SkSpecialImage> specialSrc(SkSpecialImage::internal_fromBM(proxy, src)); + if (!specialSrc) { + return false; + } + + SkAutoTUnref<SkSpecialImage> tmp(input->onFilterImage(specialSrc, + this->mapContext(ctx), + offset)); + if (!tmp) { + return false; + } + + return tmp->internal_getBM(result); } bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst, @@ -327,9 +340,15 @@ bool SkImageFilter::canComputeFastBounds() const { bool SkImageFilter::onFilterImageDeprecated(Proxy*, const SkBitmap&, const Context&, SkBitmap*, SkIPoint*) const { + // Only classes that now use the new SkSpecialImage-based path will not have + // onFilterImageDeprecated methods. For those classes we should never be + // calling this method. + SkASSERT(0); return false; } +// SkImageFilter-derived classes that do not yet have their own onFilterImage +// implementation convert back to calling the deprecated filterImage method SkSpecialImage* SkImageFilter::onFilterImage(SkSpecialImage* src, const Context& ctx, SkIPoint* offset) const { SkBitmap srcBM, resultBM; @@ -338,6 +357,7 @@ SkSpecialImage* SkImageFilter::onFilterImage(SkSpecialImage* src, const Context& return nullptr; } + // This is the only valid call to the old filterImage path if (!this->filterImageDeprecated(src->internal_getProxy(), srcBM, ctx, &resultBM, offset)) { return nullptr; } @@ -583,27 +603,39 @@ bool SkImageFilter::filterInputGPUDeprecated(int index, SkImageFilter::Proxy* pr if (!input) { return true; } - // Ensure that GrContext calls under filterImage and filterImageGPU below will see an identity - // matrix with no clip and that the matrix, clip, and render target set before this function was - // called are restored before we return to the caller. - GrContext* context = src.getTexture()->getContext(); - if (input->filterImageDeprecated(proxy, src, this->mapContext(ctx), result, offset)) { - if (!result->getTexture()) { - const SkImageInfo info = result->info(); - if (kUnknown_SkColorType == info.colorType()) { - return false; - } - SkAutoTUnref<GrTexture> resultTex( - GrRefCachedBitmapTexture(context, *result, GrTextureParams::ClampNoFilter())); - if (!resultTex) { - return false; - } - result->setPixelRef(new SkGrPixelRef(info, resultTex))->unref(); - } - return true; - } else { + + SkAutoTUnref<SkSpecialImage> specialSrc(SkSpecialImage::internal_fromBM(proxy, src)); + if (!specialSrc) { + return false; + } + + SkAutoTUnref<SkSpecialImage> tmp(input->onFilterImage(specialSrc, + this->mapContext(ctx), + offset)); + if (!tmp) { return false; } + + if (!tmp->internal_getBM(result)) { + return false; + } + + if (!result->getTexture()) { + GrContext* context = src.getTexture()->getContext(); + + const SkImageInfo info = result->info(); + if (kUnknown_SkColorType == info.colorType()) { + return false; + } + SkAutoTUnref<GrTexture> resultTex( + GrRefCachedBitmapTexture(context, *result, GrTextureParams::ClampNoFilter())); + if (!resultTex) { + return false; + } + result->setPixelRef(new SkGrPixelRef(info, resultTex))->unref(); + } + + return true; } #endif diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp index 88d90b8602..0bbe50a688 100644 --- a/src/core/SkSpecialImage.cpp +++ b/src/core/SkSpecialImage.cpp @@ -20,10 +20,12 @@ public: virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const = 0; - virtual bool onPeekPixels(SkPixmap*) const { return false; } + virtual bool testingOnlyOnPeekPixels(SkPixmap*) const { return false; } virtual GrTexture* onPeekTexture() const { return nullptr; } + virtual bool testingOnlyOnGetROPixels(SkBitmap*) const = 0; + // Delete this entry point ASAP (see skbug.com/4965) virtual bool getBitmap(SkBitmap* result) const = 0; @@ -42,14 +44,18 @@ void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPain return as_SIB(this)->onDraw(canvas, x, y, paint); } -bool SkSpecialImage::peekPixels(SkPixmap* pixmap) const { - return as_SIB(this)->onPeekPixels(pixmap); +bool SkSpecialImage::testingOnlyPeekPixels(SkPixmap* pixmap) const { + return as_SIB(this)->testingOnlyOnPeekPixels(pixmap); } GrTexture* SkSpecialImage::peekTexture() const { return as_SIB(this)->onPeekTexture(); } +bool SkSpecialImage::testingOnlyGetROPixels(SkBitmap* result) const { + return as_SIB(this)->testingOnlyOnGetROPixels(result); +} + SkSpecialSurface* SkSpecialImage::newSurface(const SkImageInfo& info) const { return as_SIB(this)->onNewSurface(info); } @@ -125,7 +131,7 @@ public: dst, paint, SkCanvas::kStrict_SrcRectConstraint); } - bool onPeekPixels(SkPixmap* pixmap) const override { + bool testingOnlyOnPeekPixels(SkPixmap* pixmap) const override { return fImage->peekPixels(pixmap); } @@ -135,6 +141,10 @@ public: return false; } + bool testingOnlyOnGetROPixels(SkBitmap* result) const override { + return false; + } + SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override { #if SK_SUPPORT_GPU GrTexture* texture = as_IB(fImage.get())->peekTexture(); @@ -156,6 +166,11 @@ private: #ifdef SK_DEBUG static bool rect_fits(const SkIRect& rect, int width, int height) { + if (0 == width && 0 == height) { + SkASSERT(0 == rect.fLeft && 0 == rect.fRight && 0 == rect.fTop && 0 == rect.fBottom); + return true; + } + return rect.fLeft >= 0 && rect.fLeft < width && rect.fLeft < rect.fRight && rect.fRight >= 0 && rect.fRight <= width && rect.fTop >= 0 && rect.fTop < height && rect.fTop < rect.fBottom && @@ -178,7 +193,7 @@ public: SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm) : INHERITED(proxy, subset, bm.getGenerationID()) , fBitmap(bm) { - if (bm.pixelRef()->isPreLocked()) { + if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) { // we only preemptively lock if there is no chance of triggering something expensive // like a lazy decode or imagegenerator. PreLocked means it is flat pixels already. fBitmap.lockPixels(); @@ -199,7 +214,7 @@ public: dst, paint, SkCanvas::kStrict_SrcRectConstraint); } - bool onPeekPixels(SkPixmap* pixmap) const override { + bool testingOnlyOnPeekPixels(SkPixmap* pixmap) const override { const SkImageInfo info = fBitmap.info(); if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) { return false; @@ -219,6 +234,11 @@ public: return true; } + bool testingOnlyOnGetROPixels(SkBitmap* result) const override { + *result = fBitmap; + return true; + } + SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override { return SkSpecialSurface::NewRaster(this->proxy(), info, nullptr); } @@ -285,6 +305,25 @@ public: return true; } + bool testingOnlyOnGetROPixels(SkBitmap* result) const override { + + const SkImageInfo info = SkImageInfo::MakeN32(this->width(), + this->height(), + this->isOpaque() ? kOpaque_SkAlphaType + : kPremul_SkAlphaType); + if (!result->tryAllocPixels(info)) { + return false; + } + + if (!fTexture->readPixels(0, 0, result->width(), result->height(), kSkia8888_GrPixelConfig, + result->getPixels(), result->rowBytes())) { + return false; + } + + result->pixelRef()->setImmutable(); + return true; + } + SkSpecialSurface* onNewSurface(const SkImageInfo& info) const override { GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info); desc.fFlags = kRenderTarget_GrSurfaceFlag; diff --git a/src/core/SkSpecialImage.h b/src/core/SkSpecialImage.h index 79fceeba6f..e80f82be96 100644 --- a/src/core/SkSpecialImage.h +++ b/src/core/SkSpecialImage.h @@ -72,6 +72,13 @@ public: static SkSpecialImage* internal_fromBM(SkImageFilter::Proxy*, const SkBitmap&); SkImageFilter::Proxy* internal_getProxy(); + // TODO: hide this when GrLayerHoister uses SkSpecialImages more fully (see skbug.com/5063) + /** + * If the SpecialImage is backed by a gpu texture, return that texture. + * The active portion of the texture can be retrieved via 'subset'. + */ + GrTexture* peekTexture() const; + protected: SkSpecialImage(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID) : fSubset(subset) @@ -94,13 +101,11 @@ protected: * * On failure, return false and ignore the pixmap parameter. */ - bool peekPixels(SkPixmap*) const; + bool testingOnlyPeekPixels(SkPixmap*) const; - /** - * If the SpecialImage is backed by a gpu texture, return that texture. - * The active portion of the texture can be retrieved via 'subset'. - */ - GrTexture* peekTexture() const; + // This entry point is for testing only. It does a readback from VRAM for + // GPU-backed special images. + bool testingOnlyGetROPixels(SkBitmap*) const; // TODO: remove this ASAP (see skbug.com/4965) SkImageFilter::Proxy* proxy() const { return fProxy; } |