| Index: src/core/SkCanvas.cpp
|
| diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
|
| index 1999f3109fb8c907509518dfe6fd6b8062b92ac7..050253fa68c4e85dcca7cf44976b2384168f36a3 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
|
| }
|
|
|
|
|