diff options
-rw-r--r-- | include/core/SkCanvas.h | 4 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 107 | ||||
-rw-r--r-- | src/core/SkSpecialImage.cpp | 24 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 1 |
4 files changed, 72 insertions, 64 deletions
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index e3b4ffb244..4d68a8e226 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -1420,6 +1420,10 @@ private: static bool BoundsAffectsClip(SaveLayerFlags); static SaveLayerFlags LegacySaveFlagsToSaveLayerFlags(uint32_t legacySaveFlags); + static void DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter, + SkBaseDevice* dst, const SkMatrix& ctm, + const SkClipStack* clipStack); + enum ShaderOverrideOpacity { kNone_ShaderOverrideOpacity, //!< there is no overriding shader (bitmap or image) kOpaque_ShaderOverrideOpacity, //!< the overriding shader is opaque diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 1999f3109f..050253fa68 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -1146,40 +1146,29 @@ int SkCanvas::saveLayer(const SaveLayerRec& origRec) { return this->getSaveCount() - 1; } -static void draw_filter_into_device(SkBaseDevice* src, const SkImageFilter* filter, - SkBaseDevice* dst, const SkMatrix& ctm) { - - SkBitmap srcBM; - -#if SK_SUPPORT_GPU - // TODO: remove this virtual usage of accessRenderTarget! It is preventing - // removal of the virtual on SkBaseDevice. - GrRenderTarget* srcRT = src->accessRenderTarget(); - if (srcRT && !srcRT->asTexture() && dst->accessRenderTarget()) { - // When both the src & the dst are on the gpu but the src doesn't have a texture, - // we create a temporary texture for the draw. - // TODO: we should actually only copy the portion of the source needed to apply the image - // filter - GrContext* context = srcRT->getContext(); - SkAutoTUnref<GrTexture> tex(context->textureProvider()->createTexture(srcRT->desc(), - SkBudgeted::kYes)); - - context->copySurface(tex, srcRT); - - GrWrapTextureInBitmap(tex, src->width(), src->height(), src->isOpaque(), &srcBM); - } else -#endif - { - srcBM = src->accessBitmap(false); - } - - SkCanvas c(dst); +void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter, + SkBaseDevice* dst, const SkMatrix& ctm, + const SkClipStack* clipStack) { + SkDraw draw; + SkRasterClip rc; + rc.setRect(SkIRect::MakeWH(dst->width(), dst->height())); + if (!dst->accessPixels(&draw.fDst)) { + draw.fDst.reset(dst->imageInfo(), nullptr, 0); + } + draw.fMatrix = &SkMatrix::I(); + draw.fRC = &rc; + draw.fClipStack = clipStack; + draw.fDevice = dst; SkPaint p; p.setImageFilter(filter->makeWithLocalMatrix(ctm)); - const SkScalar x = SkIntToScalar(src->getOrigin().x()); - const SkScalar y = SkIntToScalar(src->getOrigin().y()); - c.drawBitmap(srcBM, x, y, &p); + + int x = src->getOrigin().x() - dst->getOrigin().x(); + int y = src->getOrigin().y() - dst->getOrigin().y(); + auto special = src->snapSpecial(); + if (special) { + dst->drawSpecial(draw, special.get(), x, y, p); + } } static SkImageInfo make_layer_info(const SkImageInfo& prev, int w, int h, bool isOpaque, @@ -1270,7 +1259,7 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra } SkBaseDevice* priorDevice = this->getTopDevice(); - if (!priorDevice) { + if (nullptr == priorDevice) { SkDebugf("Unable to find device for layer."); return; } @@ -1294,15 +1283,16 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra } newDevice->setOrigin(ir.fLeft, ir.fTop); - if (rec.fBackdrop) { - draw_filter_into_device(priorDevice, rec.fBackdrop, newDevice, fMCRec->fMatrix); - } - DeviceCM* layer = new DeviceCM(newDevice, paint, this, fConservativeRasterClip, stashedMatrix); layer->fNext = fMCRec->fTopLayer; fMCRec->fLayer = layer; fMCRec->fTopLayer = layer; // this field is NOT an owner of layer + + if (rec.fBackdrop) { + DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice, + fMCRec->fMatrix, this->getClipStack()); + } } int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { @@ -1452,18 +1442,19 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPa } LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) + while (iter.next()) { SkBaseDevice* dstDev = iter.fDevice; paint = &looper.paint(); SkImageFilter* filter = paint->getImageFilter(); SkIPoint pos = { x - iter.getX(), y - iter.getY() }; if (filter) { - const SkBitmap& srcBM = srcDev->accessBitmap(false); - dstDev->drawSpriteWithFilter(iter, srcBM, pos.x(), pos.y(), *paint); + dstDev->drawSpecial(iter, srcDev->snapSpecial().get(), pos.x(), pos.y(), *paint); } else { dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); } } + LOOPER_END } @@ -2311,17 +2302,13 @@ void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const S paint = lazy.init(); } + sk_sp<SkSpecialImage> special; bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(), *paint); if (drawAsSprite && paint->getImageFilter()) { - SkBitmap bitmap; - if (!as_IB(image)->asBitmapForImageFilters(&bitmap)) { + special = this->getDevice()->makeSpecial(image); + if (!special) { drawAsSprite = false; - } else{ - // Until imagefilters are updated, they cannot handle any src type but N32... - if (bitmap.info().colorType() != kN32_SkColorType || bitmap.info().gammaCloseToSRGB()) { - drawAsSprite = false; - } } } @@ -2329,15 +2316,12 @@ void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const S while (iter.next()) { const SkPaint& pnt = looper.paint(); - if (drawAsSprite && pnt.getImageFilter()) { - SkBitmap bitmap; - if (as_IB(image)->asBitmapForImageFilters(&bitmap)) { - SkPoint pt; - iter.fMatrix->mapXY(x, y, &pt); - iter.fDevice->drawSpriteWithFilter(iter, bitmap, - SkScalarRoundToInt(pt.fX), - SkScalarRoundToInt(pt.fY), pnt); - } + if (special) { + SkPoint pt; + iter.fMatrix->mapXY(x, y, &pt); + iter.fDevice->drawSpecial(iter, special.get(), + SkScalarRoundToInt(pt.fX), + SkScalarRoundToInt(pt.fY), pnt); } else { iter.fDevice->drawImage(iter, image, x, y, pnt); } @@ -2400,11 +2384,12 @@ void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, cons bounds = &storage; } + sk_sp<SkSpecialImage> special; bool drawAsSprite = bounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(), bitmap.height(), *paint); if (drawAsSprite && paint->getImageFilter()) { - // Until imagefilters are updated, they cannot handle any src type but N32... - if (bitmap.info().colorType() != kN32_SkColorType || bitmap.info().gammaCloseToSRGB()) { + special = this->getDevice()->makeSpecial(bitmap); + if (!special) { drawAsSprite = false; } } @@ -2413,17 +2398,17 @@ void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, cons while (iter.next()) { const SkPaint& pnt = looper.paint(); - if (drawAsSprite && pnt.getImageFilter()) { + if (special) { SkPoint pt; iter.fMatrix->mapXY(x, y, &pt); - iter.fDevice->drawSpriteWithFilter(iter, bitmap, - SkScalarRoundToInt(pt.fX), - SkScalarRoundToInt(pt.fY), pnt); + iter.fDevice->drawSpecial(iter, special.get(), + SkScalarRoundToInt(pt.fX), + SkScalarRoundToInt(pt.fY), pnt); } else { iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); } } - + LOOPER_END } diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp index 8875d2248f..e3a14e57ab 100644 --- a/src/core/SkSpecialImage.cpp +++ b/src/core/SkSpecialImage.cpp @@ -18,6 +18,13 @@ #include "SkSpecialSurface.h" #include "SkSurfacePriv.h" +// Currently the raster imagefilters can only handle certain imageinfos. Call this to know if +// a given info is supported. +static bool valid_for_imagefilters(const SkImageInfo& info) { + // no support for other swizzles/depths yet + return info.colorType() == kN32_SkColorType; +} + /////////////////////////////////////////////////////////////////////////////// class SkSpecialImage_Base : public SkSpecialImage { public: @@ -315,7 +322,11 @@ sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(const SkIRect& subset, const SkSurfaceProps* props) { SkASSERT(rect_fits(subset, image->width(), image->height())); - return sk_make_sp<SkSpecialImage_Image>(subset, image, props); + if (valid_for_imagefilters(as_IB(image.get())->onImageInfo())) { + return sk_make_sp<SkSpecialImage_Image>(subset, image, props); + } else { + return nullptr; + } } /////////////////////////////////////////////////////////////////////////////// @@ -412,7 +423,16 @@ sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset, SkASSERT(nullptr == bm.getTexture()); SkASSERT(rect_fits(subset, bm.width(), bm.height())); - return sk_make_sp<SkSpecialImage_Raster>(subset, bm, props); + const SkBitmap* srcBM = &bm; + SkBitmap tmpStorage; + // ImageFilters only handle N32 at the moment, so force our src to be that + if (!valid_for_imagefilters(bm.info())) { + if (!bm.copyTo(&tmpStorage, kN32_SkColorType)) { + return nullptr; + } + srcBM = &tmpStorage; + } + return sk_make_sp<SkSpecialImage_Raster>(subset, *srcBM, props); } #if SK_SUPPORT_GPU diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index ff2806a672..8501a03d98 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -2262,6 +2262,5 @@ sk_sp<SkSpecialImage> SkPDFDevice::makeSpecial(const SkImage* image) { } sk_sp<SkSpecialImage> SkPDFDevice::snapSpecial() { - SkASSERT(false); return nullptr; } |