diff options
Diffstat (limited to 'src/record/SkRecordOpts.cpp')
-rw-r--r-- | src/record/SkRecordOpts.cpp | 68 |
1 files changed, 68 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; |