diff options
author | reed <reed@google.com> | 2016-01-07 11:28:08 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-07 11:28:08 -0800 |
commit | bfd5f171e6a3eccd7c4bede652a85fd76bcbce2a (patch) | |
tree | b46a17e4b9860d628d40480178e999fea4bc32c7 | |
parent | 133eaaacdd23fb45db47a32e854eab3ecd76f213 (diff) |
Revert[2] of "add backdrop option to SaveLayerRec"
Reverted because of picture/serialization failure
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1567063002
TBR=mtklein
Review URL: https://codereview.chromium.org/1567063002
-rw-r--r-- | gm/imagefilters.cpp | 74 | ||||
-rw-r--r-- | include/core/SkCanvas.h | 19 | ||||
-rw-r--r-- | include/private/SkRecords.h | 2 | ||||
-rw-r--r-- | samplecode/SampleApp.cpp | 9 | ||||
-rw-r--r-- | samplecode/SampleLayers.cpp | 76 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 18 | ||||
-rw-r--r-- | src/core/SkPictureFlat.h | 12 | ||||
-rw-r--r-- | src/core/SkPicturePlayback.cpp | 20 | ||||
-rw-r--r-- | src/core/SkPictureRecord.cpp | 46 | ||||
-rw-r--r-- | src/core/SkRecordDraw.cpp | 2 | ||||
-rw-r--r-- | src/core/SkRecordOpts.cpp | 10 | ||||
-rw-r--r-- | src/core/SkRecorder.cpp | 3 | ||||
-rw-r--r-- | tests/RecordOptsTest.cpp | 73 |
13 files changed, 316 insertions, 48 deletions
diff --git a/gm/imagefilters.cpp b/gm/imagefilters.cpp index 5f1ae84949..951a934d82 100644 --- a/gm/imagefilters.cpp +++ b/gm/imagefilters.cpp @@ -104,3 +104,77 @@ DEF_SIMPLE_GM(fast_slow_blurimagefilter, canvas, 620, 260) { canvas->translate(r.width() + 20, 0); } } + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#include "Resources.h" +#include "SkBlurImageFilter.h" +#include "SkMatrixConvolutionImageFilter.h" +#include "SkMorphologyImageFilter.h" +#include "SkColorMatrixFilter.h" +#include "SkColorFilterImageFilter.h" +#include "SkRRect.h" + +static void draw_set(SkCanvas* canvas, SkImageFilter* filters[], int count) { + const SkRect r = SkRect::MakeXYWH(30, 30, 200, 200); + const SkScalar offset = 250; + SkScalar dx = 0, dy = 0; + + for (int i = 0; i < count; ++i) { + canvas->save(); + SkRRect rr = SkRRect::MakeRectXY(r.makeOffset(dx, dy), 20, 20); + canvas->clipRRect(rr, SkRegion::kIntersect_Op, true); + canvas->saveLayer({ &rr.getBounds(), nullptr, filters[i], 0 }); + canvas->drawColor(0x40FFFFFF); + canvas->restore(); + canvas->restore(); + + if (0 == dx) { + dx = offset; + } else { + dx = 0; + dy = offset; + } + } +} + +DEF_SIMPLE_GM(savelayer_with_backdrop, canvas, 830, 550) { + SkColorMatrix cm; + cm.setSaturation(10); + SkAutoTUnref<SkColorFilter> cf(SkColorMatrixFilter::Create(cm)); + const SkScalar kernel[] = { 4, 0, 4, 0, -15, 0, 4, 0, 4 }; + SkImageFilter* filters[] = { + SkBlurImageFilter::Create(10, 10), + SkDilateImageFilter::Create(8, 8), + SkMatrixConvolutionImageFilter::Create({ 3, 3 }, kernel, 1, 0, { 0, 0 }, + SkMatrixConvolutionImageFilter::kClampToBlack_TileMode, + true), + SkColorFilterImageFilter::Create(cf), + }; + + const struct { + SkScalar fSx, fSy, fTx, fTy; + } xforms[] = { + { 1, 1, 0, 0 }, + { 0.5f, 0.5f, 530, 0 }, + { 0.25f, 0.25f, 530, 275 }, + { 0.125f, 0.125f, 530, 420 }, + }; + + SkPaint paint; + paint.setFilterQuality(kMedium_SkFilterQuality); + SkAutoTUnref<SkImage> image(GetResourceAsImage("mandrill_512.png")); + + canvas->translate(20, 20); + for (const auto& xform : xforms) { + canvas->save(); + canvas->translate(xform.fTx, xform.fTy); + canvas->scale(xform.fSx, xform.fSy); + canvas->drawImage(image, 0, 0, &paint); + draw_set(canvas, filters, SK_ARRAY_COUNT(filters)); + canvas->restore(); + } + + for (auto& filter : filters) { + filter->unref(); + } +} diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index d046b8ef4c..d1de626315 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -422,16 +422,27 @@ public: typedef uint32_t SaveLayerFlags; struct SaveLayerRec { - SaveLayerRec() : fBounds(nullptr), fPaint(nullptr), fSaveLayerFlags(0) {} + SaveLayerRec() + : fBounds(nullptr), fPaint(nullptr), fBackdrop(nullptr), fSaveLayerFlags(0) + {} SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0) : fBounds(bounds) , fPaint(paint) + , fBackdrop(nullptr) + , fSaveLayerFlags(saveLayerFlags) + {} + SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop, + SaveLayerFlags saveLayerFlags) + : fBounds(bounds) + , fPaint(paint) + , fBackdrop(backdrop) , fSaveLayerFlags(saveLayerFlags) {} - const SkRect* fBounds; // optional - const SkPaint* fPaint; // optional - SaveLayerFlags fSaveLayerFlags; + const SkRect* fBounds; // optional + const SkPaint* fPaint; // optional + const SkImageFilter* fBackdrop; // optional + SaveLayerFlags fSaveLayerFlags; }; int saveLayer(const SaveLayerRec&); diff --git a/include/private/SkRecords.h b/include/private/SkRecords.h index a2e9030b23..ecd73a12d9 100644 --- a/include/private/SkRecords.h +++ b/include/private/SkRecords.h @@ -10,6 +10,7 @@ #include "SkCanvas.h" #include "SkDrawable.h" +#include "SkImageFilter.h" #include "SkMatrix.h" #include "SkPath.h" #include "SkPicture.h" @@ -197,6 +198,7 @@ RECORD(Save, 0); RECORD(SaveLayer, 0, Optional<SkRect> bounds; Optional<SkPaint> paint; + RefBox<const SkImageFilter> backdrop; SkCanvas::SaveLayerFlags saveLayerFlags); RECORD(SetMatrix, 0, diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp index d200e295fb..c7a37e786c 100644 --- a/samplecode/SampleApp.cpp +++ b/samplecode/SampleApp.cpp @@ -1396,6 +1396,15 @@ void SampleWindow::afterChildren(SkCanvas* orig) { if (fUseMPD) { SkAutoTUnref<const SkPicture> picture(fRecorder.endRecording()); + + if (false) { + SkDynamicMemoryWStream wstream; + picture->serialize(&wstream); + + SkAutoTDelete<SkStream> rstream(wstream.detachAsStream()); + picture.reset(SkPicture::CreateFromStream(rstream)); + } + if (true) { if (true) { SkImageInfo info; diff --git a/samplecode/SampleLayers.cpp b/samplecode/SampleLayers.cpp index 52bf5b357b..f8ebd7c94f 100644 --- a/samplecode/SampleLayers.cpp +++ b/samplecode/SampleLayers.cpp @@ -232,8 +232,80 @@ protected: private: typedef SkView INHERITED; }; +DEF_SAMPLE( return new LayersView; ) ////////////////////////////////////////////////////////////////////////////// -static SkView* MyFactory() { return new LayersView; } -static SkViewRegister reg(MyFactory); +#include "SkBlurImageFilter.h" +#include "SkMatrixConvolutionImageFilter.h" +#include "SkMorphologyImageFilter.h" + +#include "Resources.h" +#include "SkAnimTimer.h" + +class BackdropView : public SampleView { + SkPoint fCenter; + SkScalar fAngle; + SkAutoTUnref<SkImage> fImage; + SkAutoTUnref<SkImageFilter> fFilter; +public: + BackdropView() { + fCenter.set(200, 150); + fAngle = 0; + fImage.reset(GetResourceAsImage("mandrill_512.png")); + fFilter.reset(SkDilateImageFilter::Create(8, 8)); + } + +protected: + // overrides from SkEventSink + bool onQuery(SkEvent* evt) override { + if (SampleCode::TitleQ(*evt)) { + SampleCode::TitleR(evt, "Backdrop"); + return true; + } + return this->INHERITED::onQuery(evt); + } + + void onDrawContent(SkCanvas* canvas) override { + canvas->drawImage(fImage, 0, 0, nullptr); + + const SkScalar w = 250; + const SkScalar h = 150; + SkPath path; + path.addOval(SkRect::MakeXYWH(-w/2, -h/2, w, h)); + SkMatrix m; + m.setRotate(fAngle); + m.postTranslate(fCenter.x(), fCenter.y()); + path.transform(m); + + canvas->clipPath(path, SkRegion::kIntersect_Op, true); + const SkRect bounds = path.getBounds(); + + SkPaint paint; + paint.setAlpha(0xCC); + canvas->saveLayer({ &bounds, &paint, fFilter, 0 }); + + canvas->restore(); + } + + bool onAnimate(const SkAnimTimer& timer) override { + fAngle = SkDoubleToScalar(fmod(timer.secs() * 360 / 5, 360)); + return true; + } + + SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override { + this->inval(nullptr); + return new Click(this); + } + + bool onClick(Click* click) override { + this->inval(nullptr); + fCenter = click->fCurr; + return this->INHERITED::onClick(click); + } + +private: + typedef SampleView INHERITED; +}; +DEF_SAMPLE( return new BackdropView; ) + diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index a4acbdc94d..82ceba4fa9 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -114,7 +114,6 @@ bool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() { // experimental for faster tiled drawing... //#define SK_ENABLE_CLIP_QUICKREJECT - //#define SK_TRACE_SAVERESTORE #ifdef SK_TRACE_SAVERESTORE @@ -481,7 +480,7 @@ public: // Make rawBounds include all paint outsets except for those due to image filters. rawBounds = &apply_paint_to_bounds_sans_imagefilter(*fPaint, *rawBounds, &storage); } - (void)canvas->internalSaveLayer(SkCanvas::SaveLayerRec(rawBounds, &tmp, 0), + (void)canvas->internalSaveLayer(SkCanvas::SaveLayerRec(rawBounds, &tmp), SkCanvas::kFullLayer_SaveLayerStrategy); fTempLayerForImageFilter = true; // we remove the imagefilter/xfermode inside doNext() @@ -1173,7 +1172,8 @@ int SkCanvas::saveLayer(const SaveLayerRec& origRec) { return this->getSaveCount() - 1; } -static void draw_filter_into_device(SkBaseDevice* src, SkImageFilter* filter, SkBaseDevice* dst) { +static void draw_filter_into_device(SkBaseDevice* src, const SkImageFilter* filter, + SkBaseDevice* dst, const SkMatrix& ctm) { SkBitmap srcBM; @@ -1198,9 +1198,12 @@ static void draw_filter_into_device(SkBaseDevice* src, SkImageFilter* filter, Sk SkCanvas c(dst); + SkAutoTUnref<SkImageFilter> localF(filter->newWithLocalMatrix(ctm)); SkPaint p; - p.setImageFilter(filter); - c.drawBitmap(srcBM, 0, 0, &p); + p.setImageFilter(localF); + const SkScalar x = SkIntToScalar(src->getOrigin().x()); + const SkScalar y = SkIntToScalar(src->getOrigin().y()); + c.drawBitmap(srcBM, x, y, &p); } void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) { @@ -1268,11 +1271,10 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra } device = newDev; } - device->setOrigin(ir.fLeft, ir.fTop); - if (0) { - draw_filter_into_device(fMCRec->fTopLayer->fDevice, nullptr, device); + if (rec.fBackdrop) { + draw_filter_into_device(fMCRec->fTopLayer->fDevice, rec.fBackdrop, device, fMCRec->fMatrix); } DeviceCM* layer = diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h index cbacc8e664..4eee04fcda 100644 --- a/src/core/SkPictureFlat.h +++ b/src/core/SkPictureFlat.h @@ -75,9 +75,10 @@ enum DrawType { DRAW_IMAGE_NINE, DRAW_IMAGE_RECT, - SAVE_LAYER_SAVELAYERFLAGS, + SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016, + SAVE_LAYER_SAVELAYERREC, - LAST_DRAWTYPE_ENUM = SAVE_LAYER_SAVELAYERFLAGS, + LAST_DRAWTYPE_ENUM = SAVE_LAYER_SAVELAYERREC, }; // In the 'match' method, this constant will match any flavor of DRAW_BITMAP* @@ -95,6 +96,13 @@ enum DrawAtlasFlags { DRAW_ATLAS_HAS_CULL = 1 << 1, }; +enum SaveLayerRecFlatFlags { + SAVELAYERREC_HAS_BOUNDS = 1 << 0, + SAVELAYERREC_HAS_PAINT = 1 << 1, + SAVELAYERREC_HAS_BACKDROP = 1 << 2, + SAVELAYERREC_HAS_FLAGS = 1 << 3, +}; + /////////////////////////////////////////////////////////////////////////////// // clipparams are packed in 5 bits // doAA:1 | regionOp:4 diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index 82b8f0e578..4b028f714e 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -483,11 +483,29 @@ void SkPicturePlayback::handleOp(SkReader32* reader, auto flags = SkCanvas::LegacySaveFlagsToSaveLayerFlags(reader->readInt()); canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags)); } break; - case SAVE_LAYER_SAVELAYERFLAGS: { + case SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016: { const SkRect* boundsPtr = get_rect_ptr(reader); const SkPaint* paint = fPictureData->getPaint(reader); canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, reader->readInt())); } break; + case SAVE_LAYER_SAVELAYERREC: { + SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, 0); + const uint32_t flatFlags = reader->readInt(); + if (flatFlags & SAVELAYERREC_HAS_BOUNDS) { + rec.fBounds = &reader->skipT<SkRect>(); + } + if (flatFlags & SAVELAYERREC_HAS_PAINT) { + rec.fPaint = fPictureData->getPaint(reader); + } + if (flatFlags & SAVELAYERREC_HAS_BACKDROP) { + const SkPaint* paint = fPictureData->getPaint(reader); + rec.fBackdrop = paint->getImageFilter(); + } + if (flatFlags & SAVELAYERREC_HAS_FLAGS) { + rec.fSaveLayerFlags = reader->readInt(); + } + canvas->saveLayer(rec); + } break; case SCALE: { SkScalar sx = reader->readScalar(); SkScalar sy = reader->readScalar(); diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp index 7907ee0d29..2822a1ac16 100644 --- a/src/core/SkPictureRecord.cpp +++ b/src/core/SkPictureRecord.cpp @@ -76,19 +76,44 @@ SkCanvas::SaveLayerStrategy SkPictureRecord::getSaveLayerStrategy(const SaveLaye void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) { fContentInfo.onSaveLayer(); - // op + bool for 'bounds' + // op + flatflags size_t size = 2 * kUInt32Size; + uint32_t flatFlags = 0; + if (rec.fBounds) { - size += sizeof(*rec.fBounds); // + rect + flatFlags |= SAVELAYERREC_HAS_BOUNDS; + size += sizeof(*rec.fBounds); + } + if (rec.fPaint) { + flatFlags |= SAVELAYERREC_HAS_PAINT; + size += sizeof(uint32_t); // index + } + if (rec.fBackdrop) { + flatFlags |= SAVELAYERREC_HAS_BACKDROP; + size += sizeof(uint32_t); // (paint) index + } + if (rec.fSaveLayerFlags) { + flatFlags |= SAVELAYERREC_HAS_FLAGS; + size += sizeof(uint32_t); } - // + paint index + flags - size += 2 * kUInt32Size; - - size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERFLAGS, &size); - this->addRectPtr(rec.fBounds); - this->addPaintPtr(rec.fPaint); - this->addInt(rec.fSaveLayerFlags); + const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size); + this->addInt(flatFlags); + if (flatFlags & SAVELAYERREC_HAS_BOUNDS) { + this->addRect(*rec.fBounds); + } + if (flatFlags & SAVELAYERREC_HAS_PAINT) { + this->addPaintPtr(rec.fPaint); + } + if (flatFlags & SAVELAYERREC_HAS_BACKDROP) { + // overkill, but we didn't already track single flattenables, so using a paint for that + SkPaint paint; + paint.setImageFilter(const_cast<SkImageFilter*>(rec.fBackdrop)); + this->addPaint(paint); + } + if (flatFlags & SAVELAYERREC_HAS_FLAGS) { + this->addInt(rec.fSaveLayerFlags); + } this->validate(initialOffset, size); } @@ -224,7 +249,8 @@ void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t uint32_t opSize; DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize); SkASSERT(SAVE_LAYER_SAVEFLAGS_DEPRECATED != drawOp); - SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERFLAGS == drawOp); + SkASSERT(SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016 != drawOp); + SkASSERT(SAVE == drawOp || SAVE_LAYER_SAVELAYERREC == drawOp); } #endif } diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp index 01846676b6..5ca9517d3f 100644 --- a/src/core/SkRecordDraw.cpp +++ b/src/core/SkRecordDraw.cpp @@ -78,7 +78,7 @@ template <> void Draw::draw(const NoOp&) {} #define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; } DRAW(Restore, restore()); DRAW(Save, save()); -DRAW(SaveLayer, saveLayer(SkCanvas::SaveLayerRec(r.bounds, r.paint, r.saveLayerFlags))); +DRAW(SaveLayer, saveLayer(SkCanvas::SaveLayerRec(r.bounds, r.paint, r.backdrop, r.saveLayerFlags))); DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix))); DRAW(Concat, concat(r.matrix)); diff --git a/src/core/SkRecordOpts.cpp b/src/core/SkRecordOpts.cpp index d1520adf56..0121ea54fc 100644 --- a/src/core/SkRecordOpts.cpp +++ b/src/core/SkRecordOpts.cpp @@ -177,6 +177,11 @@ struct SaveLayerDrawRestoreNooper { typedef Pattern<Is<SaveLayer>, IsDraw, Is<Restore>> Match; bool onMatch(SkRecord* record, Match* match, int begin, int end) { + if (match->first<SaveLayer>()->backdrop) { + // can't throw away the layer if we have a backdrop + return false; + } + // A SaveLayer's bounds field is just a hint, so we should be free to ignore it. SkPaint* layerPaint = match->first<SaveLayer>()->paint; if (nullptr == layerPaint) { @@ -224,6 +229,11 @@ struct SvgOpacityAndFilterLayerMergePass { Is<Restore>, Is<Restore>, Is<Restore>> Match; bool onMatch(SkRecord* record, Match* match, int begin, int end) { + if (match->first<SaveLayer>()->backdrop) { + // can't throw away the layer if we have a backdrop + return false; + } + SkPaint* opacityPaint = match->first<SaveLayer>()->paint; if (nullptr == opacityPaint) { // There wasn't really any point to this SaveLayer at all. diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp index 67429a691e..01c28dfc2b 100644 --- a/src/core/SkRecorder.cpp +++ b/src/core/SkRecorder.cpp @@ -337,7 +337,8 @@ void SkRecorder::willSave() { } SkCanvas::SaveLayerStrategy SkRecorder::getSaveLayerStrategy(const SaveLayerRec& rec) { - APPEND(SaveLayer, this->copy(rec.fBounds), this->copy(rec.fPaint), rec.fSaveLayerFlags); + APPEND(SaveLayer, + this->copy(rec.fBounds), this->copy(rec.fPaint), rec.fBackdrop, rec.fSaveLayerFlags); return SkCanvas::kNoLayer_SaveLayerStrategy; } diff --git a/tests/RecordOptsTest.cpp b/tests/RecordOptsTest.cpp index dd6c410ed4..027ea39f57 100644 --- a/tests/RecordOptsTest.cpp +++ b/tests/RecordOptsTest.cpp @@ -107,6 +107,20 @@ static void assert_savelayer_restore(skiatest::Reporter* r, SkRecordNoopSaveLayerDrawRestores(record); if (shouldBeNoOped) { assert_type<SkRecords::NoOp>(r, *record, i); + assert_type<SkRecords::NoOp>(r, *record, i+1); + } else { + assert_type<SkRecords::SaveLayer>(r, *record, i); + assert_type<SkRecords::Restore>(r, *record, i+1); + } +} + +static void assert_savelayer_draw_restore(skiatest::Reporter* r, + SkRecord* record, + int i, + bool shouldBeNoOped) { + SkRecordNoopSaveLayerDrawRestores(record); + if (shouldBeNoOped) { + assert_type<SkRecords::NoOp>(r, *record, i); assert_type<SkRecords::NoOp>(r, *record, i+2); } else { assert_type<SkRecords::SaveLayer>(r, *record, i); @@ -114,6 +128,7 @@ static void assert_savelayer_restore(skiatest::Reporter* r, } } +#include "SkBlurImageFilter.h" DEF_TEST(RecordOpts_NoopSaveLayerDrawRestore, r) { SkRecord record; SkRecorder recorder(&record, W, H); @@ -134,13 +149,13 @@ DEF_TEST(RecordOpts_NoopSaveLayerDrawRestore, r) { recorder.saveLayer(nullptr, nullptr); recorder.drawRect(draw, opaqueDrawPaint); recorder.restore(); - assert_savelayer_restore(r, &record, 0, true); + assert_savelayer_draw_restore(r, &record, 0, true); // Bounds don't matter. recorder.saveLayer(&bounds, nullptr); recorder.drawRect(draw, opaqueDrawPaint); recorder.restore(); - assert_savelayer_restore(r, &record, 3, true); + assert_savelayer_draw_restore(r, &record, 3, true); // TODO(mtklein): test case with null draw paint @@ -148,29 +163,36 @@ DEF_TEST(RecordOpts_NoopSaveLayerDrawRestore, r) { recorder.saveLayer(nullptr, &translucentLayerPaint); recorder.drawRect(draw, opaqueDrawPaint); recorder.restore(); - assert_savelayer_restore(r, &record, 6, false); + assert_savelayer_draw_restore(r, &record, 6, false); // No change: layer paint has an effect. recorder.saveLayer(nullptr, &xfermodeLayerPaint); recorder.drawRect(draw, opaqueDrawPaint); recorder.restore(); - assert_savelayer_restore(r, &record, 9, false); + assert_savelayer_draw_restore(r, &record, 9, false); // SaveLayer/Restore removed: we can fold in the alpha! recorder.saveLayer(nullptr, &alphaOnlyLayerPaint); recorder.drawRect(draw, translucentDrawPaint); recorder.restore(); - assert_savelayer_restore(r, &record, 12, true); + assert_savelayer_draw_restore(r, &record, 12, true); // SaveLayer/Restore removed: we can fold in the alpha! recorder.saveLayer(nullptr, &alphaOnlyLayerPaint); recorder.drawRect(draw, opaqueDrawPaint); recorder.restore(); - assert_savelayer_restore(r, &record, 15, true); + assert_savelayer_draw_restore(r, &record, 15, true); const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, record, 16); REPORTER_ASSERT(r, drawRect != nullptr); REPORTER_ASSERT(r, drawRect->paint.getColor() == 0x03020202); + + // saveLayer w/ backdrop should NOT go away + SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(3, 3)); + recorder.saveLayer({ nullptr, nullptr, filter, 0}); + recorder.drawRect(draw, opaqueDrawPaint); + recorder.restore(); + assert_savelayer_draw_restore(r, &record, 18, false); } static void assert_merge_svg_opacity_and_filter_layers(skiatest::Reporter* r, @@ -222,25 +244,38 @@ DEF_TEST(RecordOpts_MergeSvgOpacityAndFilterLayers, r) { int index = 0; { + SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(3, 3)); + // first (null) should be optimized, 2nd should not + SkImageFilter* filters[] = { nullptr, filter.get() }; + // Any combination of these should cause the pattern to be optimized. SkRect* firstBounds[] = { nullptr, &bounds }; SkPaint* firstPaints[] = { nullptr, &alphaOnlyLayerPaint }; SkRect* secondBounds[] = { nullptr, &bounds }; SkPaint* secondPaints[] = { &opaqueFilterLayerPaint, &translucentFilterLayerPaint }; - for (size_t i = 0; i < SK_ARRAY_COUNT(firstBounds); ++ i) { - for (size_t j = 0; j < SK_ARRAY_COUNT(firstPaints); ++j) { - for (size_t k = 0; k < SK_ARRAY_COUNT(secondBounds); ++k) { - for (size_t m = 0; m < SK_ARRAY_COUNT(secondPaints); ++m) { - recorder.saveLayer(firstBounds[i], firstPaints[j]); - recorder.save(); - recorder.clipRect(clip); - recorder.saveLayer(secondBounds[k], secondPaints[m]); - recorder.restore(); - recorder.restore(); - recorder.restore(); - assert_merge_svg_opacity_and_filter_layers(r, &record, index, true); - index += 7; + for (auto outerF : filters) { + bool outerNoOped = !outerF; + for (auto innerF : filters) { + for (size_t i = 0; i < SK_ARRAY_COUNT(firstBounds); ++ i) { + for (size_t j = 0; j < SK_ARRAY_COUNT(firstPaints); ++j) { + for (size_t k = 0; k < SK_ARRAY_COUNT(secondBounds); ++k) { + for (size_t m = 0; m < SK_ARRAY_COUNT(secondPaints); ++m) { + bool innerNoOped = !secondBounds[k] && !secondPaints[m] && !innerF; + + recorder.saveLayer({firstBounds[i], firstPaints[j], outerF, 0}); + recorder.save(); + recorder.clipRect(clip); + recorder.saveLayer({secondBounds[k], secondPaints[m], innerF, 0}); + recorder.restore(); + recorder.restore(); + recorder.restore(); + assert_merge_svg_opacity_and_filter_layers(r, &record, index, + outerNoOped); + assert_savelayer_restore(r, &record, index + 3, innerNoOped); + index += 7; + } + } } } } |