aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-05-07 14:47:44 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-05-07 14:47:44 +0000
commitf5bf3cf0257dc3d18932bde51f8eae33442e071f (patch)
tree8d7ae45129cc5eed271e88f94fbf6476dc0d526b /src
parent059ee7c1b0e0b86cb91490a099920fba98f77a49 (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.cpp68
-rw-r--r--src/record/SkRecordOpts.h4
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*);