| Index: src/record/SkRecordOpts.cpp
|
| diff --git a/src/record/SkRecordOpts.cpp b/src/record/SkRecordOpts.cpp
|
| index aaa611cf392cf6126b5548f9c5f4e1bcb6a46e59..5b648f4215e5bcfae6e2878981b0e8b28b7ed948 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;
|
|
|