diff options
author | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-05-07 14:47:44 +0000 |
---|---|---|
committer | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-05-07 14:47:44 +0000 |
commit | f5bf3cf0257dc3d18932bde51f8eae33442e071f (patch) | |
tree | 8d7ae45129cc5eed271e88f94fbf6476dc0d526b /src | |
parent | 059ee7c1b0e0b86cb91490a099920fba98f77a49 (diff) |
Add SaveLayer-Draw-Restore optimization.
This is like SkPictureRecord's remove_save_layer1 but works with all draw calls.
Interesting patterns removed:
SaveLayer-DrawRect-Restore: Silk SKPs, desk_weather
SaveLayer-DrawPath-Restore: desk_carsvg, desk_wowwiki, tabl_androidpolice
SaveLayer-DrawPosTextH-Restore: tabl_android_police
There may be others, but I stopped looking.
BUG=skia:2378
R=robertphillips@google.com, mtklein@google.com
Author: mtklein@chromium.org
Review URL: https://codereview.chromium.org/269813010
git-svn-id: http://skia.googlecode.com/svn/trunk@14610 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/record/SkRecordOpts.cpp | 68 | ||||
-rw-r--r-- | src/record/SkRecordOpts.h | 4 |
2 files changed, 72 insertions, 0 deletions
diff --git a/src/record/SkRecordOpts.cpp b/src/record/SkRecordOpts.cpp index aaa611cf39..5b648f4215 100644 --- a/src/record/SkRecordOpts.cpp +++ b/src/record/SkRecordOpts.cpp @@ -16,6 +16,7 @@ using namespace SkRecords; void SkRecordOptimize(SkRecord* record) { // TODO(mtklein): fuse independent optimizations to reduce number of passes? SkRecordNoopSaveRestores(record); + SkRecordNoopSaveLayerDrawRestores(record); SkRecordAnnotateCullingPairs(record); SkRecordReduceDrawPosTextStrength(record); // Helpful to run this before BoundDrawPosTextH. SkRecordBoundDrawPosTextH(record); @@ -69,6 +70,73 @@ void SkRecordNoopSaveRestores(SkRecord* record) { while (apply(&pass, record)); // Run until it stops changing things. } +// For some SaveLayer-[drawing command]-Restore patterns, merge the SaveLayer's alpha into the +// draw, and no-op the SaveLayer and Restore. +struct SaveLayerDrawRestoreNooper { + typedef Pattern3<Is<SaveLayer>, IsDraw, Is<Restore> > Pattern; + + bool onMatch(SkRecord* record, Pattern* pattern, unsigned begin, unsigned end) { + SaveLayer* saveLayer = pattern->first<SaveLayer>(); + if (saveLayer->bounds != NULL) { + // SaveLayer with bounds is too tricky for us. + return false; + } + + SkPaint* layerPaint = saveLayer->paint; + if (NULL == layerPaint) { + // There wasn't really any point to this SaveLayer at all. + return KillSaveLayerAndRestore(record, begin); + } + + SkPaint* drawPaint = pattern->second<SkPaint>(); + if (drawPaint == NULL) { + // We can just give the draw the SaveLayer's paint. + // TODO(mtklein): figure out how to do this clearly + return false; + } + + const uint32_t layerColor = layerPaint->getColor(); + const uint32_t drawColor = drawPaint->getColor(); + if (!IsOnlyAlpha(layerColor) || !IsOpaque(drawColor) || HasAnyEffect(*layerPaint)) { + // Too fancy for us. Actually, as long as layerColor is just an alpha + // we can blend it into drawColor's alpha; drawColor doesn't strictly have to be opaque. + return false; + } + + drawPaint->setColor(SkColorSetA(drawColor, SkColorGetA(layerColor))); + return KillSaveLayerAndRestore(record, begin); + } + + static bool KillSaveLayerAndRestore(SkRecord* record, unsigned saveLayerIndex) { + record->replace<NoOp>(saveLayerIndex); // SaveLayer + record->replace<NoOp>(saveLayerIndex+2); // Restore + return true; + } + + static bool HasAnyEffect(const SkPaint& paint) { + return paint.getPathEffect() || + paint.getShader() || + paint.getXfermode() || + paint.getMaskFilter() || + paint.getColorFilter() || + paint.getRasterizer() || + paint.getLooper() || + paint.getImageFilter(); + } + + static bool IsOpaque(SkColor color) { + return SkColorGetA(color) == SK_AlphaOPAQUE; + } + static bool IsOnlyAlpha(SkColor color) { + return SK_ColorTRANSPARENT == SkColorSetA(color, SK_AlphaTRANSPARENT); + } +}; +void SkRecordNoopSaveLayerDrawRestores(SkRecord* record) { + SaveLayerDrawRestoreNooper pass; + apply(&pass, record); +} + + // Replaces DrawPosText with DrawPosTextH when all Y coordinates are equal. struct StrengthReducer { typedef Pattern1<Is<DrawPosText> > Pattern; diff --git a/src/record/SkRecordOpts.h b/src/record/SkRecordOpts.h index 6db7abca61..ad8c3bcfc7 100644 --- a/src/record/SkRecordOpts.h +++ b/src/record/SkRecordOpts.h @@ -17,6 +17,10 @@ void SkRecordOptimize(SkRecord*); // Turns logical no-op Save-[non-drawing command]*-Restore patterns into actual no-ops. void SkRecordNoopSaveRestores(SkRecord*); +// For some SaveLayer-[drawing command]-Restore patterns, merge the SaveLayer's alpha into the +// draw, and no-op the SaveLayer and Restore. +void SkRecordNoopSaveLayerDrawRestores(SkRecord*); + // Annotates PushCull commands with the relative offset of their paired PopCull. void SkRecordAnnotateCullingPairs(SkRecord*); |