Chromium Code Reviews| Index: src/record/SkRecordOpts.cpp |
| diff --git a/src/record/SkRecordOpts.cpp b/src/record/SkRecordOpts.cpp |
| index aaa611cf392cf6126b5548f9c5f4e1bcb6a46e59..080dca74c11c772cec2323f7ed60effc24bb95c6 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,72 @@ 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(); |
|
robertphillips
2014/05/07 14:28:15
In some cases we could (in the distant future) com
mtklein
2014/05/07 14:38:14
Oh, right. Noted. Seems everything I could find
|
| + if (!IsOnlyAlpha(layerColor) || !IsOpaque(drawColor) || HasAnyEffect(*layerPaint)) { |
| + // Too fancy for us. |
| + 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; |